跳至主要內容

測試 API

Deno 語言伺服器支援一組自訂 API 以啟用測試。這些 API 旨在提供資訊,以啟用 vscode 的測試 API,但其他語言伺服器用戶端可以使用這些 API 來提供類似的介面。

功能

用戶端和伺服器都應該支援實驗性的 testingApi 功能

interface ClientCapabilities {
experimental?: {
testingApi: boolean;
};
}
interface ServerCapabilities {
experimental?: {
testingApi: boolean;
};
}

當支援測試 API 的 Deno 版本遇到支援此功能的客戶端時,它會初始化處理測試偵測的程式碼,並開始提供啟用它的通知。

還要注意的是,當測試 API 功能啟用時,測試程式碼鏡片將不再傳送給客戶端。

設定

有特定設定會變更語言伺服器的行為

  • deno.testing.args - 執行測試時將作為引數提供的字串陣列。這與 deno test 子指令的運作方式相同。
  • deno.testing.enable - 啟用或停用測試伺服器的二進位旗標

通知

伺服器會在特定條件下傳送通知給客戶端。

deno/testModule

當伺服器發現包含測試的模組時,它會透過傳送 deno/testModule 通知和 TestModuleParams 的酬載來通知客戶端。

Deno 以這種方式建構

  • 一個模組可以包含 n 個測試。
  • 一個測試可以包含 n 個步驟。
  • 一個步驟可以包含 n 個步驟。

當 Deno 對測試模組進行靜態分析時,它會嘗試識別任何測試和測試步驟。由於在 Deno 中宣告測試的動態方式,它們無法總是靜態識別,只能在執行模組時識別。此通知旨在處理更新客戶端時的這兩種情況。當測試被靜態發現時,通知 kind 將為 "replace",當測試或步驟在執行時被發現時,通知 kind 將為 "insert"

當測試文件在編輯器中編輯,並且從客戶端收到 textDocument/didChange 通知時,這些變更的靜態分析將在伺服器端執行,如果測試已變更,客戶端將收到通知。

當客戶端收到 "replace" 通知時,它可以安全地「取代」測試模組表示,而當收到 "insert" 時,它應遞迴嘗試新增至現有表示。

對於測試模組,textDocument.uri 應作為任何表示的唯一 ID(因為它是指向唯一模組的字串 URL)。TestData 項目包含唯一的 id 字串。此 id 字串是伺服器追蹤測試的識別資訊的 SHA-256 雜湊。

interface TestData {
/** The unique ID for this test/step. */
id: string;

/** The display label for the test/step. */
label: string;

/** Any test steps that are associated with this test/step */
steps?: TestData[];

/** The range of the owning text document that applies to the test. */
range?: Range;
}

interface TestModuleParams {
/** The text document identifier that the tests are related to. */
textDocument: TextDocumentIdentifier;

/** A indication if tests described are _newly_ discovered and should be
* _inserted_ or if the tests associated are a replacement for any existing
* tests. */
kind: "insert" | "replace";

/** The text label for the test module. */
label: string;

/** An array of tests that are owned by this test module. */
tests: TestData[];
}

deno/testModuleDelete

當伺服器正在觀察的測試模組被刪除時,伺服器將發出 deno/testModuleDelete 通知。收到通知時,客戶端應移除測試模組的表示及其所有子測試和測試步驟。

interface TestModuleDeleteParams {
/** The text document identifier that has been removed. */
textDocument: TextDocumentIdentifier;
}

deno/testRunProgress

當從客戶端要求 deno/testRun 時,伺服器將透過 deno/testRunProgress 通知支援該測試執行的進度。

客戶端應處理這些訊息並更新任何 UI 表示。

狀態變更表示在 TestRunProgressParams.message.kind 屬性中。狀態為

  • "enqueued" - 測試或測試步驟已排隊進行測試。
  • "skipped" - 測試或測試步驟已略過。當 Deno 測試將 ignore 選項設定為 true 時,會發生這種情況。
  • "started" - 測試或測試步驟已開始。
  • "passed" - 測試或測試步驟已通過。
  • "failed" - 測試或測試步驟已失敗。這是用來表示測試架構的錯誤,而不是測試本身,但 Deno 目前不支援此區別。
  • "errored" - 測試或測試步驟已發生錯誤。有關錯誤的更多資訊將會在 .message.messages 屬性中。
  • "end" - 測試執行已結束。
interface TestIdentifier {
/** The test module the message is related to. */
textDocument: TextDocumentIdentifier;

/** The optional ID of the test. If not present, then the message applies to
* all tests in the test module. */
id?: string;

/** The optional ID of the step. If not present, then the message only applies
* to the test. */
stepId?: string;
}

interface TestMessage {
/** The content of the message. */
message: MarkupContent;

/** An optional string which represents the expected output. */
expectedOutput?: string;

/** An optional string which represents the actual output. */
actualOutput?: string;

/** An optional location related to the message. */
location?: Location;
}

interface TestEnqueuedStartedSkipped {
/** The state change that has occurred to a specific test or test step.
*
* - `"enqueued"` - the test is now enqueued to be tested
* - `"started"` - the test has started
* - `"skipped"` - the test was skipped
*/
type: "enqueued" | "started" | "skipped";

/** The test or test step relating to the state change. */
test: TestIdentifier;
}

interface TestFailedErrored {
/** The state change that has occurred to a specific test or test step.
*
* - `"failed"` - The test failed to run properly, versus the test erroring.
* currently the Deno language server does not support this.
* - `"errored"` - The test errored.
*/
type: "failed" | "errored";

/** The test or test step relating to the state change. */
test: TestIdentifier;

/** Messages related to the state change. */
messages: TestMessage[];

/** An optional duration, in milliseconds from the start to the current
* state. */
duration?: number;
}

interface TestPassed {
/** The state change that has occurred to a specific test or test step. */
type: "passed";

/** The test or test step relating to the state change. */
test: TestIdentifier;

/** An optional duration, in milliseconds from the start to the current
* state. */
duration?: number;
}

interface TestOutput {
/** The test or test step has output information / logged information. */
type: "output";

/** The value of the output. */
value: string;

/** The associated test or test step if there was one. */
test?: TestIdentifier;

/** An optional location associated with the output. */
location?: Location;
}

interface TestEnd {
/** The test run has ended. */
type: "end";
}

type TestRunProgressMessage =
| TestEnqueuedStartedSkipped
| TestFailedErrored
| TestPassed
| TestOutput
| TestEnd;

interface TestRunProgressParams {
/** The test run ID that the progress message applies to. */
id: number;

/** The message*/
message: TestRunProgressMessage;
}

要求

伺服器處理兩個不同的要求

deno/testRun

若要要求語言伺服器執行一組測試,客戶端會傳送 deno/testRun 要求,其中包含將在未來回應中傳送給客戶端的測試執行 ID、測試執行的類型,以及要包含或排除的任何測試模組或測試。

目前 Deno 僅支援 "run" 類型的測試執行。"debug""coverage" 都計畫在未來支援。

當沒有包含的測試模組或測試時,表示應執行所有已發現的測試模組和測試。當包含測試模組,但沒有任何測試 ID 時,表示應包含該測試模組中的所有測試。一旦識別出所有測試,任何已排除的測試都會被移除,而已解決的測試組會在回應中以 "enqueued" 傳回。

由於測試步驟的宣告和執行方式具有動態特性,因此無法透過此 API 包含或排除測試步驟。

interface TestRunRequestParams {
/** The id of the test run to be used for future messages. */
id: number;

/** The run kind. Currently Deno only supports `"run"` */
kind: "run" | "coverage" | "debug";

/** Test modules or tests to exclude from the test run. */
exclude?: TestIdentifier[];

/** Test modules or tests to include in the test run. */
include?: TestIdentifier[];
}

interface EnqueuedTestModule {
/** The test module the enqueued test IDs relate to */
textDocument: TextDocumentIdentifier;

/** The test IDs which are now enqueued for testing */
ids: string[];
}

interface TestRunResponseParams {
/** Test modules and test IDs that are now enqueued for testing. */
enqueued: EnqueuedTestModule[];
}

deno/testRunCancel

如果客戶端想要取消目前執行的測試,它會傳送 deno/testRunCancel 要求,其中包含要取消的測試 ID。回傳的回應會是布林值 true(如果測試已取消)或 false(如果無法取消)。在取消測試時,仍會傳送適當的測試進度通知。

interface TestRunCancelParams {
/** The test id to be cancelled. */
id: number;
}