Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az MTP-kiszolgáló mód lehetővé teszi, hogy egy szerkesztő, IDE, egyéni teszt felhasználói felület vagy más teszteszköz elindítson egy tesztalkalmazást, és a JSON-RPC-n keresztül vezesse a felderítést és a végrehajtást. Használja a szerver módot, ha az eszközének tesztmetaadatokra, a kiválasztott tesztek futtatására, előrehaladási frissítésekre vagy eredmény-artefaktumokra van szüksége a terminálkimenet elemzése nélkül. Normál parancssori és CI-futtatások esetén futtassa közvetlenül a tesztalkalmazást, vagy használja dotnet test.
Állandó kapcsolat nélküli egyszeri felderítéshez használja a --list-tests json elemet. Meglévő VSTest-ügyfélhez lásd a Programozott tesztfelderítés és -végrehajtás című témakört.
Indítsa el a nyilvános JSON-RPC-kiszolgálót a --server jsonrpc vagy --server használatával.
Important
A .NET SDK egy külön belső bináris protokollt használ.--server dotnettestcli Ne adja át ezt az értéket.
dotnet test konfigurálja az átviteli és protokollargumentumokat.
Csak forrásként használt ügyfélprogram használata
Az MTP 2.4 egy canonical JSON-RPC-ügyfelet biztosít. Adja hozzá a Microsoft. Testing.Platform.ServerMode.Client.Sources csomag. A csomag futásidejű szerelvény hozzáadása helyett C#-forrást injektál a projektbe.
A csak forrásoldali kialakítás a következőket biztosítja:
- Nincs futtatókörnyezeti DLL vagy további üzembehelyezési függőség.
- Natív AOT-kompatibilis, tükröződésmentes szerializálás.
- Az MTP-kiszolgálóval azonos adattárból származó protokolltípusok és szerializálási kód.
Az injektált MtpServerClient, IMtpServerClientés a protokolltípusok inicializálhatják a kapcsolatot, felderíthetik a teszteket, futtathatnak teszteket, kérhetik a kiszolgáló kilépését, és jelentést tehetnek a tesztcsomópont frissítéséről. Az összes injektált típus megmarad internal a fogyasztó szerelvényben. A kliens kezeli a folyamat indítását, az adatátvitelt, az üzenetek keretezését és a szerializálást; nem kell saját kezűleg megvalósítania a JSON-RPC-t.
A csomag lefordítja a C# forrást. Ha Visual Basicből vagy más .NET-nyelvből szeretné használni az ügyfélprogramot, vegyen fel hivatkozást egy olyan C#-osztálytárra, amely az injektált típusok köré épített saját nyilvános API-t tesz elérhetővé, ahogy az alábbi példa mutatja.
Tesztek felderítése és futtatása a .NET-ben
Ez a példa a csak forrást tartalmazó klienscsomag 2.5.2-es verzióját használja, és a .NET 10-et célozza meg. Először hozzon létre egy MTP-kompatibilis tesztalkalmazást, majd adja meg a kliensnek a lefordított .dll vagy futtatható fájl elérési útját.
A megosztott C# segédprogram felderíti a teszteket, kinyomtatja az egyes csomópontok szerializálható metaadatait, és futtatja a felderített teszteket a UID alapján. Egy részhalmaz futtatásához válassza ki a szükséges UID-ket a felderítési frissítésekből, és csak ezeket az UID-ket adja át a RunTestsAsync-nak. Ne használjon megjelenített neveket tesztazonosítóként.
using System.Text.Json;
using Microsoft.Testing.Platform.ServerMode.Client;
namespace TestClientSample;
public static class TestClient
{
public static async Task<int> DiscoverAndRunAsync(
string testApplicationPath,
CancellationToken cancellationToken = default)
{
string path = Path.GetFullPath(testApplicationPath);
var testUids = new HashSet<string>(StringComparer.Ordinal);
using (IMtpServerClient client = await MtpServerClient.LaunchAsync(
path, cancellationToken: cancellationToken))
{
try
{
MtpServerCapabilities capabilities =
await client.InitializeAsync(cancellationToken);
if (capabilities.MultiConnectionProvider)
{
throw new NotSupportedException("A passive controller connection can't discover or run tests.");
}
if (!capabilities.SupportsDiscovery)
{
throw new NotSupportedException("The test application doesn't support discovery.");
}
client.LogReceived += (_, log) => Console.Error.WriteLine(log.Message);
client.TestNodesUpdated += (_, update) =>
{
foreach (MtpTestNodeUpdate change in update.Changes)
{
Console.WriteLine(JsonSerializer.Serialize(change.Node));
if (change.NodeType != "group"
&& change.ExecutionState == "discovered"
&& change.Uid is string uid)
{
testUids.Add(uid);
}
}
};
await client.DiscoverTestsAsync(cancellationToken);
await client.ExitAsync(cancellationToken);
}
finally
{
await client.ShutdownAsync();
}
}
if (testUids.Count == 0)
{
Console.Error.WriteLine("No tests were discovered.");
return 8;
}
var completedUids = new HashSet<string>(StringComparer.Ordinal);
bool hasUnsuccessfulResult = false;
using IMtpServerClient runClient = await MtpServerClient.LaunchAsync(
path, cancellationToken: cancellationToken);
try
{
MtpServerCapabilities capabilities =
await runClient.InitializeAsync(cancellationToken);
if (capabilities.MultiConnectionProvider)
{
throw new NotSupportedException("A passive controller connection can't discover or run tests.");
}
runClient.LogReceived += (_, log) => Console.Error.WriteLine(log.Message);
runClient.TestNodesUpdated += (_, update) =>
{
foreach (MtpTestNodeUpdate change in update.Changes)
{
Console.WriteLine(JsonSerializer.Serialize(change.Node));
if (change.Uid is string uid
&& testUids.Contains(uid)
&& change.ExecutionState is string state
&& state is not ("discovered" or "in-progress")
&& (!change.Node.TryGetValue("retry.is-superseded", out object? superseded)
|| superseded is not true))
{
completedUids.Add(uid);
hasUnsuccessfulResult |= state is not ("passed" or "skipped");
}
}
};
MtpRunResult result = await runClient.RunTestsAsync(testUids, cancellationToken);
foreach (MtpAttachment artifact in result.Artifacts)
{
Console.WriteLine($"Artifact: {artifact.Uri}");
}
await runClient.ExitAsync(cancellationToken);
if (hasUnsuccessfulResult || !testUids.All(completedUids.Contains))
{
Console.Error.WriteLine("A selected test failed or didn't report a final result.");
return 2;
}
return 0;
}
finally
{
await runClient.ShutdownAsync();
}
}
}
A segéd egy külön tesztelési folyamatot indít el a felderítéshez és a végrehajtáshoz, így nincs szükség a(z) MtpServerCapabilities.MultiRequestSupport elemre. Egy folyamat újbóli felhasználásához ellenőrizze ezt a képességet InitializeAsync után, mielőtt több kérést ad ki. A felderítés kérése előtt ellenőrizze a(z) SupportsDiscovery elemet is.
Important
A csak forrásoldali kliens indítási segédprogramjai egy JSON-RPC kapcsolatot kezelnek. A 2.5.2-es verzióban nem fogadják el és irányítják a vezérlőalapú bővítmények által használt további kapcsolatokat. A Windows rendszeren történő TRX-jelentéskészítés például elindíthat egy vezérlőt, amelynek passzív kapcsolata az aktív tesztgazda elé érkezik. Olyan kapcsolat, amelyben a(z) MultiConnectionProvider értéke true, csak a frissítéseket és artefaktumokat küldi le; ne küldjön felderítési vagy futtatási kéréseket erre a kapcsolatra. A példa elutasítja ezt a kapcsolatot.
Vezérlőalapú jelentések esetén futtassa a tesztalkalmazást a CLI-n keresztül, vagy dotnet test használjon olyan eszköz-klienset, amely kezeli a protokoll további kapcsolatait. Az egykapcsolatos ügyfél továbbra is fogadhat olyan artefaktumokat, amelyeket az aktív tesztgazda közzétesz.
A C# és Visual Basic konzolprojektek egyaránt a C# segédprojektre hivatkoznak:
using TestClientSample;
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: DiscoverAndRun <test-application-path>");
return 1;
}
return await TestClient.DiscoverAndRunAsync(args[0]);
Futtassa bármelyik konzolprojektet a tesztalkalmazás elérési útjával argumentumként:
dotnet run --project <client-project> -- <test-application-path>
A példa 0 értéket ad vissza, ha minden kiválasztott UID-nek van végleges eredménye, és minden nem felülírt végleges eredmény passed-et vagy skipped-t jelez, 2-at sikertelen vagy hiányzó végleges eredmények esetén, és 8-et, ha a felderítés nem ad vissza teszteket. Ezek a döntések a mintaügyfélhez tartoznak. A befejezett RunTestsAsync feladat azt jelenti, hogy a protokollkérelem befejeződött, nem pedig azt, hogy a tesztek átmentek.
MtpRunResult.Artifacts futtatási artefaktumokat tartalmaz, nem pedig pass/fail ítéletet. A test-node frissítéseinek használatával állapítsa meg a teszteredményeket.
Több találathoz ugyanaz a UID tartozhat. A példa csak akkor hagyja figyelmen kívül a korábbi újrapróbálkozási kísérleteket, ha retry.is-supersededtrue; a UID-egyenlőség önmagában nem alapoz meg újrapróbálkozást. Egy később sikeres vagy kihagyott eredmény nem törölhet egy korábbi, nem felülírt hibát.
Frissítések és metaadatok feldolgozása
Iratkozzon fel a TestNodesUpdated elemre a felderítés vagy végrehajtás előtt. Olvassa ki az egyes frissítésekből a Changes elemet, és azonosítsa a csomópontokat a Uid alapján. Az ügyfél olyan kényelmi tulajdonságokkal rendelkezik, mint a DisplayName, ExecutionState, ErrorMessageés DurationInMilliseconds. Olvassa el a Node szótárt a többi szerializált mezővel kapcsolatban, beleértve a traits elemet és a keretrendszerspecifikus tulajdonságokat is.
Az MSTest tulajdonságokként teszi közzé a tesztkategóriákat és az egyéni TestProperty értékeket. A metaadatok elérhetősége a tesztelési keretrendszertől és attól függ, hogy mit tesz közzé a felderítés során. Az tetszőleges attribútumok és a memóriabeli IProperty implementációk nem lépik át automatikusan a folyamathatárt. A hordozható kulcs-érték metaadatok közzétételéhez használja a nyilvános TestMetadataProperty típust. A platform- és kompatibilitási rétegek más szerializálható mezőket is biztosíthatnak; a belső tulajdonságtípusok nem bővítmény API-k. További részletekért lásd: Tesztcsomópont tulajdonságai.
Ne számítson arra, hogy a JSON-RPC csomópont szótára megegyezzen a --list-tests json dokumentuméval. A transzportok különböző mezőelrendezéseket használnak. Emellett ne feltételezzük, hogy minden keretrendszer a VSTest-specifikus vstest.* mezőket bocsátja ki.
A kliens sorrendben dolgozza fel a frissítéseket, és meghívja a megfelelő kezelőket, mielőtt a felderítési vagy futtatási feladat befejeződik. Nincs szükség késleltetésre a végleges frissítés megvárásához. A kezelők szinkron módon futnak a kliens olvasási ciklusában, ezért ne blokkolja őket, és ne várja meg szinkron módon egy másik kliensművelet befejeződését. Irányítsa a nagy erőforrás-igényű feladatokat vagy a felhasználói felület frissítéseit a megfelelő szálra.
Adjon át egy megszakítási tokent a felderítési vagy futtatási metódusoknak, hogy a protokollon keresztül megszakítást kérhessen. Ha a tesztelési keretrendszer támogatja a faszűrőket, használjon DiscoverTestsWithFilterAsync vagy RunTestsWithFilterAsync egy MTP-faszűrő kifejezést a tesztek kiválasztásához anélkül, hogy először létrehoz egy UID-gyűjteményt. Ezek a metódusok nem fogadják el a VSTest --filter kifejezéseket.
Ügyfélkövetelményeknek való megfelelés
Használja a C# 12 vagy újabb verziót. A csomag tiszteletben tartja a projekt nyelvi verzió beállítását. Ha a cél keretrendszer alapértelmezés szerint egy korábbi C#-verzióra van beállítva, állítsa LangVersion értékét 12.0 vagy újabb verzióra. A csomag belső kompatibilitási típusokat is biztosít a .NET Framework 4.6.2-hez és a netstandard2.0-hoz.
A csomag hozzáadása előtt távolítsa el az MTP-ügyfél kézzel írt másolatát a duplikált belső típusok elkerülése érdekében.
Indítási modell kiválasztása
Ha külső folyamatként szeretné elindítani a tesztalkalmazást, használja MtpServerClient.LaunchAsynca következőt: . Az ügyfél birtokolja ezt a gyermekfolyamatot, és szükség esetén megszakítja azt a lebontás során.
Ha egy külső tesztalkalmazást szeretne konfigurálni egy adott környezethez, állítsa be MtpServerClientOptions.EnvironmentVariables az indítás előtt. A gyermekfolyamat örökli a szülő környezetét, a megadott értékeknek a gyermekfolyamatban való alkalmazásával. Ezek a beállítások nem módosítják a folyamaton belüli gazda környezetét.
Minden kliens egy tesztalkalmazást vezérel. Több tesztalkalmazás esetén hozzon létre egy klienst minden alkalmazáshoz, és összesítse az eredményeket az eszközben.
Ha olyan beágyazott gazdagépen vagy UI-szálas környezetben dolgozik, amely nem tudja használni a Process.Start elemet, használja a MtpServerClient.LaunchInProcessAsync elemet. A metódus egy aszinkron visszahíváson keresztül futtatja a tesztalkalmazást az aktuális folyamatban. Ne blokkolja az indító szálat, mert a visszahívási függvény és a kliens ugyanabban a folyamatban fut.
Mindkét indítási modell egy visszacsatolási TCP-átvitelt használ. A böngészős WebAssembly nem tudja létrehozni a szükséges eseményfigyelőt, ezért a folyamaton belüli indítás PlatformNotSupportedException kivételt eredményez. A folyamaton belüli indítás nem biztosít alternatív WebAssembly-átvitelt.
A kliens leállítása
Az ügyfél és az elindított alkalmazás leállításához a hívó szál blokkolása nélkül hívja meg a következőt: IMtpServerClient.ShutdownAsync() Az aszinkron metódus elkerüli a felhasználói felület szálával kapcsolatos válaszkészségi és holtponti problémákat a beágyazott gazdagép-környezetekben.
Folyamaton belüli gazda esetén a MtpServerClientOptions.ServerShutdownTimeout azt szabályozza, hogy a leállítás mennyi ideig várjon azután, hogy az ügyfél lezárta a transportot. Az alapértelmezett érték 30 másodperc. A leállítás után olvassa el a ServerExitCode elemet a visszahívás kilépési kódjának lekéréséhez. Az érték megmarad null , amíg az alkalmazás fut, vagy ha az alkalmazás nem ad vissza egy kilépési kódot.
Az ügyfél állapottartásának deklarálása
Az MTP 2.4.1-től kezdve állítsa be a nullable MtpServerClientOptions.IsStateful beállítást annak leírására, hogy az ügyfél hogyan használja fel a test-node frissítéseket:
| Value | Nyilatkozat |
|---|---|
true |
Az ügyfél megőrzi a munkamenethez tartozó, címzhető tesztcsomópontok készletét, és az egyes csomópontok utolsó ismert állapotát mindaddig megőrzi, amíg egy másik frissítés nem módosítja azt, ahogyan azt egy IDE tesztfelfedezője is teheti. |
false |
Az ügyfél a tesztcsomópont állapotának megőrzése nélkül feldolgozza a frissítéseket. |
null (alapértelmezett) |
Az ügyfél nem deklarálja a képességet. Az inicializálási kapcsolatfelvétel kihagyja a mezőt. |
Az ügyfél explicit logikai értéket küld a kísérleti capabilities.testing.isStateful protokollképességen keresztül. Az állapottartás független a kapcsolat élettartamától és a kiszolgáló MultiRequestSupport képességétől. Az ügyfél nem válik állapotalapúvá csupán azért, mert több kérést küld ugyanazon a kapcsolaton keresztül.
Az MTP 2.4.0 egy nem null értékű logikai beállítást használ, amelynek alapértelmezett értéke a false. Egy be nem jelentett képesség megőrzéséhez használja az MTP 2.4.1-es vagy újabb verzióját.
Keretrendszerben vagy bővítményben a kísérleti IClientInfo szolgáltatással vizsgálja meg a deklarációt. Olvasson clientInfo.Capabilities.IsStateful egy konzervatív logikai eredményhez, amely false, ha a képesség nincs deklarálva. Az MTP 2.4.1-es vagy újabb verziójában a ClientCapabilitiesExtensions.GetIsStateful() megőrzi a nem deklarált, explicit módon állapot nélküli és állapottal rendelkező ügyfelek közötti különbséget.
Protokollkompatibilitás egyeztetése
Az MTP 2.4-től kezdve a kiszolgáló módú protokoll egyeztetése független az MTP NuGet-csomag verziójától. Az ügyfél deklarálja az általa támogatott protokollverziókat, és a kiszolgáló kiválaszt egy közös verziót. Ha nincs átfedés a támogatott verziók között, a tesztalkalmazás a ProtocolError kilépési kóddal (12) kilép ahelyett, hogy inkompatibilis kommunikációs szerződéssel folytatná.
Az üzenetek érvényesítéséhez használja a verziószámozott kiszolgáló módú 1.0 JSON-sémát . A System.Text.Json és a Jsonite szerializálók ugyanazt a sémát és hibaborítékot követik.