Skip to content

Latest commit

 

History

History
66 lines (44 loc) · 3.38 KB

tests-how-unit-tests-organize-code.md

File metadata and controls

66 lines (44 loc) · 3.38 KB

How Unit Tests Organize the Code

Laravel segregates all automated tests into a 3 groups:

  • Unit tests, which test isolated application components
  • Feature (HTTP) tests, which test entire HTTP route handling
  • Browser tests (performed via Laravel Dusk), which test application behavior Browser, including JavaScript

Despite "Feature" and "Browser" tests are the closest to the project's raw use case definition, they should not dominate over the application's tests. In fact the most tests should be written at "Unit" level.

Open App\Http\Controllers\Api\Me\RentController see method store(). It has a complex logic, which defines whether particular user can rent a particular book. There are various scenarios, like subscription is missing or rent quota is exhausted and so on. However, instead of cover all the scenarios via "Feature" test, we cover them via "Unit" test for the separated entity App\Rules\AllowBookRentRule.

Open Tests\Unit\Rules\AllowBookRentRuleTest, see how all the possible scenarios are covered by tests.

Open Tests\Feature\Me\RentsTest, see that it contains only a basic test for store scenario.

"Browser" test is always heavier than "Feature" test, and "Feature" test is always heavier than "Unit" one. You should always try to cover all complex logic at "Unit" tests level. If you do this right, it will organize the application's class structure of itself. You will have to extract extra classes and methods, creating extra abstraction layers in order to be able writing "Unit" test for them.

See also:

Test Structure

Each test should consist of 3 virtual parts:

  • "Given" ("Initial state")
  • "When" ("Action")
  • "Then" ("Assertions")

When proper written, a particular unit test sounds like a project's use case. Test "formalizes" raw use cases.

See Tests\Unit\Services\Subscription\SubscriptionProlongerTest for example.

Tests Performance

Tests should run fast, otherwise they have no purpose. Each time before making a git commit or git push you should always run the entire tests, ensuring nothing is broken by your change-set. If tests execution takes several hours, it ends up with developers ignoring this vital step, and eventually break of the application.

Auth Testing

There is no need to re-test same thing over and over. In particular this applies to the "auth" feature. Laravel provides and abstraction layer for the auth user handling via "Auth Guards". Thus, you should test user's login only once at the dedicated test, at all other places use actingAs() test method to mock up auth guard.

Open Tests\Feature\Auth\LoginTest, see the login logic tested at HTTP level. Open Tests\Feature\Me\RentsTest, see actingAs() usage for logged-in user mock.