1、Laravel TDD - 开箱即用的默认测试

作者: 温新

图书: 【Laravel 11.x TDD (Pest)基础】

阅读: 31

时间: 2025-02-09 22:58:49

系统环境

  • Rocky Linux 9.1
  • PHP 8.2.3
  • Laravel 11.x
  • Laravel Installer 5.11.2

TDD 说明

本系列是面向没有使用过驱动测试开发的开发者,使用更加简介高效的 Pest 进行驱动测试开发。

项目使用 Laravel 安装器进行安装,在开始之前请务必安装 Laravel 安装器。

安装项目

$ laravel new pest

 ┌ Would you like to install a starter kit? ────────────────────┐
 │ No starter kit                                               │
 └──────────────────────────────────────────────────────────────┘

 ┌ Which testing framework do you prefer? ──────────────────────┐
 │ Pest                                                         │
 └──────────────────────────────────────────────────────────────┘

默认会生成一个 tests 文件夹,,其中包含 FeatureUnit 文件夹,分单是功能测试和单元测试。

功能测试 VS 单元测试

在大数情况下,我们应从功能测试开始,首先测试功能是否正常,而单元测试则着重于单独的、代码单元进行进行,更像是类中的函数一样。

PEST 与 PHPUnit

之前,Laravel 一直使用提 PHP Unit ,但是随着 Pest 愈发简介高效,Laravel 11 使用 Pest 作为功能测试框架,但是,在安装项目时,Laravel 也提供了选择,可以根据自己的喜好来决定使用 Pest 还是 PHP Unit。

它们具有如下特点:

  • Pest:简洁,更快,具有一些额外的功能,如架构测试
  • PHP Unit:更加标准

运行测试

使用 Pest 编写测试时,每个测试都以函数 test()it() 开头。使用 it() 函数时,Pest 会将其附加到测试的名称中。

现在,让我们看看 tests/Feature 文件夹中的 ExampleTest

<?php

it('returns a successful response', function () {
    $response = $this->get('/');

    $response->assertStatus(200);
});

当我们访问首页时且成功后,将状态断言为 200,表示请求成功。现在,我们开始测试:

$ php artisan test

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true                                                                                 0.01s  

# 这是我们的功能测试
   PASS  Tests\Feature\ExampleTest
  ✓ it returns a successful response                                                                  0.26s  

  Tests:    2 passed (2 assertions)
  Duration: 0.43s

我们可以看到两个测试成功通过:一个来自 Unit,一个来自 Feature 测试。

如果测试没有通过会发生什么?我们修改状态来看看。

// tests/Feature/ExampleTest.php

it('returns a successful response', function () {
    $response = $this->get('/');
 
    $response->assertStatus(403);
});

测试失败的情况:

]$ php artisan test

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true                                                                                 0.01s  

   FAIL  Tests\Feature\ExampleTest
  ⨯ it returns a successful response                                                                  0.26s  
  ─────────────────────────────────────────────────────────────────────────────────────────────────────────  
   FAILED  Tests\Feature\ExampleTest > it returns a successful response                                      
  Expected response status code [403] but received 200.
Failed asserting that 200 is identical to 403.

# 测试失败的情况
  at tests/Feature/ExampleTest.php:6
      2▕ 
      3▕ it('returns a successful response', function () {
      4▕     $response = $this->get('/');
      5▕ 
  ➜   6▕     $response->assertStatus(403);
      7▕ });
      8▕ 


  Tests:    1 failed, 1 passed (2 assertions)
  Duration: 0.39s

现在我们可以看到 1 个通过1 个失败

在里面,我们可以看到哪个测试失败了,在哪个代码行上。它还显示实际错误 Expected response status code [403] but received 200. 。这就是失败的测试的样子。

扩展:PHP Unit 测试

如果使用提 PHP Unit 以该如何编写?

对于 PHPUnit,ExampleTest 是一个扩展 TestCase,每个要测试的测试或功能都是一个函数。

将其与 Pest 进行比较,在 Pest 中,不需要创建类。相反,只需立即编写测试函数。

test 类可以包含多个函数。在每个函数中,执行一些代码,然后测试或断言发生了某些事情以及它是否正确。函数名称应以 test_ 前缀开头。下面是默认示例:

public function test_the_application_returns_a_successful_response(): void
{
    $response = $this->get('/');
 
    $response->assertStatus(200);
}

运行测试

$ php artisan test

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true

   PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response                                                     0.24s  

  Tests:    2 passed (2 assertions)
  Duration: 0.33s

请注意,终端中测试的名称来自函数的命名。在命名 test 函数时,不要害怕使用较长的名称,因为当有人在该功能中启动测试时,这些名称将是可读的。

PHPUnit 测试失败的示例:

public function test_the_application_returns_a_successful_response(): void
{
    $response = $this->get('/');
 
    $response->assertStatus(403);
    
}

再次进行测试

$ php artisan test

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true                                                                                 0.01s  

   FAIL  Tests\Feature\ExampleTest
  ⨯ the application returns a successful response                                                     0.24s  
  ─────────────────────────────────────────────────────────────────────────────────────────────────────────  
   FAILED  Tests\Feature\ExampleTest > the application returns a successful response                         
  Expected response status code [403] but received 200.
Failed asserting that 200 is identical to 403.

  at tests/Feature/ExampleTest.php:17
     13▕     public function test_the_application_returns_a_successful_response(): void
     14▕     {
     15▕         $response = $this->get('/');
     16▕ 
  ➜  17▕         $response->assertStatus(403);
     18▕     }
     19▕ }
     20▕ 


  Tests:    1 failed, 1 passed (2 assertions)
  Duration: 0.34s

so easy

TDD 是不是很简单?我们什么都没有做就已经跑起来了。

大多数功能测试只是启动一些页面或调用一些 API,然后测试它是否成功。

如果只是想遍历所有页面或端点并检查它们是否返回 200(或另一个成功消息),这类测试有一个特殊的名字:称为 冒烟测试。当你刚开始进行测试时,冒烟测试是一个很好的起点。可以在不深入复杂测试语法的情况下,确保你的应用程序在添加新功能后能够正常工作。

接下来关于自动化测试的所有深入主题都是为了探讨不同的断言方法和模拟特定页面或功能场景的方式。这正是我们将在接下来的文章中涵盖的内容。通过这些课程,将学习如何更细致地测试你的应用,确保每个部分都按预期工作。

请登录后再评论