壓力測試

壓力測試是一種測試,用於檢查您的應用程式在現實或極端條件下(視您設定的場景而定)的穩定性和可靠性。例如,您可以使用壓力測試來驗證您的應用程式是否可以處理大量的請求或大量的資料。

在 Pest 中,您可以結合壓力測試和期望值 API 的功能,確保隨著時間的推移不會出現穩定性和可靠性倒退。這對於在新的版本發布或新部署之後驗證您的應用程式是否穩定和可靠很有用。

在幕後,此專案採用 k6,一個強大的開源負載測試工具,用於評估 API、微服務和網站的效能。k6 的授權方式為AGPL-3.0 授權條款,當第一次使用外掛程式時會下載 k6 二進制檔案。

若要開始使用 Pest 的壓力測試外掛程式(主要稱為 Stressless),您需要透過 Composer 要求 stressless 外掛程式。

1composer require pestphp/pest-plugin-stressless --dev

要求外掛程式之後,您可以透過兩種不同的方式開始使用它

  • 使用 stress 指令:當您想要快速壓力測試 URL,而不需要設定結果期望值時很有用。
  • 使用 stress() 函式:當您想要壓力測試 URL 並設定結果期望值時很有用。

測試外部網域或本機 IP 位址?當從外部網路負載測試網域時,您可以現實地了解您的應用程式在典型使用者負載下的效能。這包括網路延遲和真實網路流量等因素。然而,當在您的網路內測試本機 IP 位址時,重點在於了解在受控環境中,您的內部基礎架構的效能,而沒有網路或 DNS 解析時間等外部變數。這對於識別您自己的網路或伺服器內的潛在瓶頸,以及調整內部應用程式或伺服器的效能特別有用。這包括更有效地設定 PHP FPM 等任務。

壓力指令

stress 指令在您想要快速壓力測試 URL、分析結果,且不需要設定結果期望值時很有用。這是啟動壓力測試最快的途徑,而且會直接在終端機上進行。

若要開始,你可以使用 stress 指令,並提供你想要執行壓力測試的 URL

1./vendor/bin/pest stress example.com

預設情況下,壓力測試持續時間為 5 秒。不過,你可以使用 --duration 選項自訂這個數值

1./vendor/bin/pest stress example.com --duration=5

此外,同時執行要求的數量會為 1。不過,你也可以使用 --concurrency 選項自訂這個數值

1./vendor/bin/pest stress example.com --concurrency=5

同時執行值表示將對給定的 URL 進行同時的執行要求數,舉個例子,如果你將同時執行設定為 5,Pest 會持續對所提供的 URL 進行 5 次同時的執行要求,直到壓力測試持續時間結束為止。

你可能想要注意你設定的同時執行要求數量,如果你設定過多同時執行要求,你可能使你的應用程式、伺服器或到達速率限制/防火牆不堪負荷。

如果你想指定在壓力測試中使用的 HTTP 方法,你可以使用提供的 deletegetheadoptionspatchputpost 選項其中之一,透過使用 optionspatchput 選項,你可以在要求中指定選用的有效負載引數,透過使用 post 選項,你必須提供有效負載引數。

1./vendor/bin/pest stress example.com/articles
2# or
3./vendor/bin/pest stress example.com/articles --get
4# or
5./vendor/bin/pest stress example.com/articles --head
6# or
7./vendor/bin/pest stress example.com/articles --options
8# or
9./vendor/bin/pest stress example.com/articles --options='{"name": "Nuno"}'
10# or
11./vendor/bin/pest stress example.com/articles/1 --patch
12# or
13./vendor/bin/pest stress example.com/articles/1 --patch='{"name": "Nuno"}'
14# or
15./vendor/bin/pest stress example.com/articles --put
16# or
17./vendor/bin/pest stress example.com/articles --put='{"name": "Nuno"}'
18# or
19./vendor/bin/pest stress example.com/articles --post='{"name": "Nuno"}'
20# or
21./vendor/bin/pest stress example.com/articles/1 --delete

壓力測試一旦完成,Pest 將會顯示壓力測試結果的摘要。

壓力測試函式

一旦你開始了解壓力測試如何運作,你可能會想要對壓力測試結果開始設定預期,舉例來說,你可能會希望確認平均回應時間永遠小於 100 毫秒,而這正是 stress() 函式發揮作用的地方。

若要開始,只要建立一個常規的測試,並使用 stress() 函式對指定的 URL 執行壓力測試

1<?php
2 
3use function Pest\Stressless\stress;
4 
5it('has a fast response time', function () {
6 $result = stress('example.com');
7 
8 expect($result->requests()->duration()->med())->toBeLessThan(100); // < 100.00ms
9});

預設情況下,壓力測試持續時間為 10 秒,不過,你可以使用 for()->seconds() 方法自訂這個值

1$result = stress('example.com')->for(5)->seconds();

此外,同時執行要求的數量會為 1,不過,你也可以使用 concurrently 方法自訂這個數值

1$result = stress('example.com')->concurrently(requests: 2)->for(5)->seconds();

在任何時候,你都可以 dd 壓力測試結果來查看它的詳細資料,就像你在使用 stress 指令時所做的一樣)

1$result = stress('example.com')->dd();
2 //->dump();
3 //->verbosely();

如果你想要指定壓力測試中使用的 HTTP 方法,你可以使用提供的 deletegetheadoptionspatchputpost 方法,其中之一,透過使用 optionspatchput 方法,你可以在要求中指定選用的有效負載引數,透過使用 post 方法,你必須提供有效負載引數。

1$result = stress('example.com/articles/1')->delete();
2// or
3$result = stress('example.com/articles')->get();
4// or
5$result = stress('example.com/articles')->head();
6// or
7$result = stress('example.com/articles')->options();
8// or
9$result = stress('example.com/articles')->options(["name" => "Nuno"]);
10// or
11$result = stress('example.com/articles/1')->patch();
12// or
13$result = stress('example.com/articles/1')->patch(["name" => "Nuno"]);
14// or
15$result = stress('example.com/articles')->put();
16// or
17$result = stress('example.com/articles')->put(["name" => "Nuno"]);
18// or
19$result = stress('example.com/articles')->post(["name" => "Nuno"]);

stress() 函式會傳回壓力測試結果,你可以用它來設定預期,以下是可用的方法清單

要求持續時間

傳回整體要求持續時間(毫秒)。

1$result->requests()->duration()->med();
2 // ->min();
3 // ->max();
4 // ->p90();
5 // ->p95();

要求數量

傳回已發出要求數量。

1$result->requests()->count();

要求速率

傳回每秒發出要求數量。

1$result->requests()->rate();

要求失敗數量

傳回失敗要求數量。

1$result->requests()->failed()->count();

要求失敗率

傳回每秒失敗要求數量。

1$result->requests()->failed()->rate();

要求時間距離第一個位元組持續時間/ TTFB

以毫秒為單位回傳要求時間距離第一個位元組持續時間。

1$result->requests()->ttfb()->duration()->med();
2 // ->min();
3 // ->max();
4 // ->p90();
5 // ->p95();

要求 DNS 查詢持續時間

網路中客戶端與 DNS 伺服器間的延遲會影響此指標。

以毫秒為單位回傳要求 DNS 查詢持續時間。

1$result->requests()->dnsLookup()->duration()->med();
2 // ->min();
3 // ->max();
4 // ->p90();
5 // ->p95();

要求 TLS 交握持續時間

網路中客戶端與伺服器間的延遲會影響此指標。

以毫秒為單位回傳要求 TLS 交握持續時間。

1$result->requests()->tlsHandshaking()->duration()->med();
2 // ->min();
3 // ->max();
4 // ->p90();
5 // ->p95();

要求下載持續時間

網路中客戶端與伺服器間的延遲會影響此指標。

以毫秒為單位回傳要求下載持續時間。

1$result->requests()->download()->duration()->med();
2 // ->min();
3 // ->max();
4 // ->p90();
5 // ->p95();

要求下載資料計數

以位元組為單位回傳要求下載資料計數。

1$result->requests()->download()->data()->count();

要求下載資料速率

以每秒位元組為單位回傳要求下載資料速率。

1$result->requests()->download()->data()->rate();

要求上傳持續時間

網路中客戶端與伺服器間的延遲會影響此指標。

以毫秒為單位回傳要求上傳持續時間。

1$result->requests()->upload()->duration()->med();
2 // ->min();
3 // ->max();
4 // ->p90();
5 // ->p95();

要求上傳資料計數

以位元組為單位回傳要求上傳資料計數。

1$result->requests()->upload()->data()->count();

要求上傳資料速率

以每秒位元組為單位回傳要求上傳資料速率。

1$result->requests()->upload()->data()->rate();

測試運作並行性

回傳壓力測試期間進行的同時要求數量,此數量是使用 --concurrency 選項或 concurrently 方法設定的。

1$result->testRun()->concurrency();

測試運作持續時間

回傳壓力測試期間持續時間,此時間是使用 --duration 選項或 for()->seconds() 方法設定的。

1$result->testRun()->duration();

在此,我們已經瞭解如何使用 Pest 的壓力測試外掛程式 (又稱為 stressless) 來對特定 URL 進行壓力測試,並對結果設定預期值。接著,我們來探討如何測試測試程式碼的涵蓋率:測試涵蓋率