Laravel Dusk 控制檯是一款 Laravel 擴展包,可以爲你的 Dusk 測試套件提供漂亮的可視面板。經過它,你能夠可視化運行 Dusk 測試時涉及的各個步驟,以及查看每一個步驟的 DOM 快照。這對於調試瀏覽器測試、並搞清楚後臺作了什麼十分有用。同時,你還可使用瀏覽器的調試工具來檢查 DOM 快照。php
<img src="https://user-gold-cdn.xitu.io...;h=728&f=png&s=505665" class="rm-style">html
除了可視面板,此擴展包還提供了 Laravel Dusk 測試監視器。在你對 Dusk 測試進行修改後,便會自動執行測試過程。前端
該擴展包受到 Javascript 前端測試框架 —— Cypress 的強烈啓發。laravel
查看本擴展包,請移步 GitHub 。git
Laravel Dusk 提供了富有表現力的、易於使用的瀏覽器自動化和測試 API。使用 Laravel Dusk編寫測試用例,像在真正的瀏覽器上同樣。好比,當你想在網站上測試拖放功能時,想要測試Vue組件或其餘與 Javascript 相關功能,那麼你沒法使用 Laravels HTTP 測試 API 自己進行測試。github
我認爲 Laravel Dusk 是一個很是棒的軟件包而且能夠簡化瀏覽器測試。
如下是一個用戶註冊的示例測試,以便你能夠了解 Laravel Dusk 的功能:web
public function test_can_register() { $faker = Factory::create(); $this->browse(function($browser) use ($faker) { $password = $faker->password(9); $browser->visit('/register') ->assertSee('Register') ->type('name', $faker->name) ->type('email', $faker->safeEmail) ->type('password', $password) ->type('password_confirmation', $password) ->press('Register') ->assertPathIs('/home'); }); }
要了解更多關於 Laravel Dusk 以及如何開始使用本身的瀏覽器測試的更多信息,請查看 官方文檔。chrome
在介紹 Laravel Dusk 控制檯內部如何運行以前,讓咱們先瞄一眼如何在 Laravel 應用內安裝並使用這個擴展包。瀏覽器
以下步驟假定你已經按照 官方文檔 成功地安裝了 Laravel Dusk;或者甚至你已經寫好了一些 Dusk 測試。服務器
首先,使用 Composer 安裝本擴展包。
composer require --dev beyondcode/dusk-dashboard
接下來,打開 Laravel Dusk 生成的 DuskTestCase.php
。你能夠在 tests
目錄裏找到這個文件。
請務必使用本擴展包的測試用例(Test case
)做爲基類,而不是 Laravel Dusk 的測試用例。稍後我再告訴你內部原理。
找到此行:
use Laravel\Dusk\TestCase as BaseTestCase;
使用以下內容替換:
use BeyondCode\DuskDashboard\Testing\TestCase as BaseTestCase;
搞定。
如今你可使用以下命令啓動 Laravel Dusk 控制檯,並執行你的測試了。
php artisan dusk:dashboard
相似這樣的界面便會展現在你的面前:
<img src="https://user-gold-cdn.xitu.io...;h=728&f=png&s=287914" class="rm-style">
只需按下「Start Tests」按鈕,便可運行 Laravel Dusk 測試,並觀察到你的應用被測試時的輸出,以及所發生的行爲。
隨後,你便會看到 Dusk 測試產生的各類事件出如今你的控制檯上。
還有一種啓動 Dusk 測試的方法是,只要編輯任意一個測試文件而後保存便可。Laravel Dusk 控制檯內置了文件監視器。
你能夠經過點擊展現在列表中的測試行爲,來調試和檢查它們。點擊後,你將會看到 DOM 快照,表示當此行爲被記錄時的 HTML 頁面狀態。若此行爲以某種方式操做過 DOM,那麼你也能夠點擊 「Before」和「After」按鈕在事件發生「以前」或「以後」的 DOM 快照之間進行切換。
以下,一個按下「Register」按鈕的小例子:
有時候,查看運行測試時發生的有關 XHR 請求的其餘信息可能會頗有用。例如:你網站上又一個按鈕,它將對某個服務端執行 GET 請求。
Dusk Dashboard 容許您記錄 XHR 事件,並顯示響應狀態和響應路徑。
默認狀況下 XHR 請求檢查不會啓用,由於它須要你修改瀏覽器功能。
要啓用 XHR 的請求記錄,打開你的 DuskTestCase.php
,在文件裏,有個 driver
方法,用於設置不一樣測試操做的 WebDriver。因爲此程序包須要對此驅動程序的功能進行一些調整,所以須要使用 $this->enableNetworkLogging
方法調用來封裝 DesiredCapabilities
對象。
protected function driver() { $options = (new ChromeOptions)->addArguments([ '--disable-gpu', '--headless', '--window-size=1920,1080', ]); return RemoteWebDriver::create( 'http://localhost:9515', $this->enableNetworkLogging( DesiredCapabilities::chrome()->setCapability( ChromeOptions::CAPABILITY, $options ) ) ); }
經過添加此功能,該程序包將啓用記錄 XHR 請求和響應信息所需的功能。
基本思路十分簡單:運行一個 WebSocket 服務,控制檯用戶鏈接到這個 WebSocket 服務,接着 PHPUnit 便會將瀏覽器事件和失敗信息發送至全部 WebSocket 鏈接。
如下是具體的實現方式:
在內部,此擴展包向你的 Laravel 應用內添加了一個名爲 StartDashboardCommand
的命令。當此命令被執行時,就會 啓動 一個由 Ratchet 開發的 WebSocket 服務。最初我考慮基於我同 Freek 一塊兒開發的 Laravel Websockets 實現此功能,然而隨後就斃了這個想法。緣由很簡單,此擴展包僅能用做開發依賴項,而且我不須要 Pusher 或 Laravel 廣播功能,由於廣播是經過 PHPUnit 內部實現的。
譯者注:Freek 意指 Freek Van der Herten。
另,截至目前,此擴展包也已經發布 v1.0.x 穩定版本。
接下來,我添加兩條路由到 WebSocket 服務。
$dashboardRoute = new Route('/dashboard', ['_controller' => new DashboardController()], [], [], null, [], ['GET']); $this->app->routes->add('dashboard', $dashboardRoute); $eventRoute = new Route('/events', ['_controller' => new EventController()], [], [], null, [], ['POST']); $this->app->routes->add('events', $eventRoute);
$dashboardRoute
是一條普通 HTTP 控制器路由,用於輸出 Laravel Dusk 控制檯的 HTML 視圖。
就是這麼簡單,它只作一件事——返回 HTML 視圖:
class DashboardController extends Controller { public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) { $connection->send( str(new Response( 200, ['Content-Type' => 'text/html'], file_get_contents(__DIR__.'/../../../resources/views/index.html') )) ); $connection->close(); } }
$eventRoute
一樣是一個 HTTP 路由,但只容許 POST
請求。它被用來在 PHPUnit 和 WebSocket 客戶端之間通信。
一樣十分簡單,也只作一件事——接收 POST 數據,並廣播給全部已鏈接的 WebSocket 客戶端:
class EventController extends Controller { public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { try { /* * 以下即爲從 PHPUnit 測試發來的 POST 數據, * 發送到已鏈接的客戶端。 */ foreach (Socket::$connections as $connection) { $connection->send($request->getBody()); } $conn->send(str(new Response(200))); } catch (Exception $e) { $conn->send(str(new Response(500, [], $e->getMessage()))); } $conn->close(); } }
這是整個擴展包最乏味的部分。由於若想收集全部 Laravel Dusk 方法,並將它們廣播到 WebSocket 鏈接,那麼必須代理全部的消息再收集它們。
在本擴展包自定義的 TestCase
類裏,咱們可以重寫(override
)瀏覽器實例被建立的過程。那麼,此處就是我注入自定義的瀏覽器(Browser
)類的地方。它負責代理現有方法並收集全部行爲,同時轉發給 WebSocket 鏈接。
protected function newBrowser($driver) { return new Browser($driver); }
沒什麼高端操做。接下來,我本來想直接建立一個新類,傳給它 Laravel Dusk 的瀏覽器類,隨後使用 __call
魔術方法代理全部的方法。這可以省下一大堆代碼,但也會引出兩個問題:
用戶沒法使用 IDE 自動完成、方法提示功能。
對我來講有點忍不了,我認爲這是個很是重要的特性 —— 尤爲是對於測試工具來講。開發者並不瞭解 API 的輸入和輸出,所以須要 IDE 的提示。
另外一個問題是,我不只僅想在瀏覽器行爲發生後記錄 DOM 快照,在某些特定的行爲發生前,一樣想記錄快照。
因此這就是我爲什麼不得不像下面這樣,代理全部 Laravel Dusk 方法:
/** @inheritdoc */ public function assertTitle($title) { $this->actionCollector->collect(__FUNCTION__, func_get_args(), $this); return parent::assertTitle($title); }
好了,這樣我便能收集並記錄各個行爲,且依然維持着 IDE 自動完成功能。棒棒噠!
如今你能看到這裏的 actionCollector
是 PHPUnit 和 WebSocket 客戶端之間的橋樑。它收集得到的信息,並用例如測試名稱和 WebSocket POST 推送的端點數據來豐富它:
protected function pushAction(string $name, array $payload) { try { $this->client->post('http://127.0.0.1:'.StartDashboardCommand::PORT.'/events', [ RequestOptions::JSON => [ 'channel' => 'dusk-dashboard', 'name' => $name, 'data' => $payload, ], ]); } catch (\Exception $e) { // Dusk-Dashboard 服務器多是關閉的。沒必要驚慌。 } }
它由 try-catch 包裹來保證即便在 Dusk Dashboard 服務器關閉時 Laravel Dusk 也能正常運行。
最後,值得注意的是,此擴展包在它的面板界面裏也有不少說道。它由 TailwindCSS 和 Vue 驅動來展現到來的事件以及過濾它們等等。你能夠在這 這 查看起始頁面的代碼。
差很少就這些了。
更多翻譯文章請見 PHP / Laravel 開發者社區 https://laravel-china.org/top...