Laravel 5.4 came out on Tuesday, and the first thing I installed was Dusk. Browser tests without a Selenium server: it talks to ChromeDriver directly, the API is fluent, and a failed test leaves a screenshot behind.
My first test was the login path:
$this->browse(function ($browser) {
$browser->visit('/login')
->type('email', 'user@example.com')
->type('password', 'secret')
->press('Log in')
->assertPathIs('/home');
});
It passed on the third run. The first run failed because the button on the test box had different text. The second failed because a JS animation was slower than the wait. This is the normal life of a browser test. It sees the real application, and the real application moves.
So writing them is solved, Dusk made that easy. How many to write is the question. My answer is very few. A browser test costs seconds where a unit test costs milliseconds, and it goes red when a designer renames a button. Cover every branch of business logic this way and the suite cries wolf every week, and after a month nobody looks at red.
I keep the pyramid boring. Many unit tests for logic. Some integration tests for queries and services. Browser tests only where a failure costs money: registration, login, checkout, the payment callback. On one project I counted such paths honestly. Eight. Not eighty.
And do not assert markup in Dusk. Assert what the user gets: assertPathIs, assertSee on the text that matters. The deeper you look into the HTML, the more you test the template, and the template is not the contract.