Laravel如何進行自動化測試?以下這篇文章透過使用 PHPUnit 和 PEST 的簡單範例來了解如何在 Laravel 中開始測試,希望對大家有幫助。
在我們談論任何程式語言的自動化測試或單元測試時,一般有兩類人:
- 那些不寫自動化測試並認為他們在浪費時間的人
- 那些寫測試然後無法想像沒有他們的工作的人
所以,通過這篇文章,我將試圖說服前者,看看它的好處,看看在Laravel 開始自動化測試是多麼容易。 【相關推薦:laravel影片教學】
首先,讓我們談談「為什麼」,然後我將展示一些非常基本的「如何做測試」的範例。
為什麼需要自動化測試
自動化測試並不複雜:它們只是為你執行部分程式碼並報告任何錯誤。這是描述它們的最簡單的方式。想像一下,你正在應用程式中啟動一項新功能,然後一個機器人助理會為你手動測試新功能,同時測試新程式碼是否不會破壞舊功能的任何內容。
這樣的好處是:自動重新測試所有功能。這似乎是額外的工作,但如果你不告訴那個「機器人」去做,那麼你應該自己手動做,對吧?還是你在沒有詳細測試的情況下推出新功能,希望用戶回報錯誤?我諷刺地稱這種方法為「手指交叉驅動的開發」。
隨著應用程式的每項新功能,自動化測試的回報越來越高。
- 功能1:手動節省X 分鐘的測試時間
- 功能2:節省2X 分鐘- 再次用於功能2 和功能1
- 功能3:節省3X 分鐘…
- 等等。
你應該明白了。想像一下你的應用程式在一兩年內,團隊中的新開發人員甚至不知道「功能 1」如何運作或如何重現它以進行測試。所以,你未來的自己會非常感謝你寫自動化測試。
當然,如果你認為你的專案是一個非常短期的項目,並且你不太關心它的未來… 不,我相信你的好意,所以讓我告訴你開始測試是多麼容易。
開始我們第一個自動化測試
要在 Laravel 中執行第一個自動化測試,你不需要寫任何程式碼。是的,你沒看錯。一切都已經在預設的 Laravel 安裝中進行了配置和準備,包括第一個真正的基本範例。
你可以嘗試安裝一個Laravel 專案並立即執行第一個測試:
laravel new project cd project php artisan test
按照正常預期,終端將會輸出以下結果:
PASS Tests\Unit\ExampleTest ✓ that true is true PASS Tests\Feature\ExampleTest ✓ the application returns a successful response Tests: 2 passed Time: 0.10s
如果我們看一下預設的Laravel /tests
資料夾,其中有兩個檔案。
tests/Feature/ExampleTest.php:
class ExampleTest extends TestCase { public function test_the_application_returns_a_successful_response() { $response = $this->get('/'); $response->assertStatus(200); } }
你不需要了解任何語法即可讀懂這段程式碼的意思:載入首頁並檢查HTTP 狀態碼是否「200 OK」。
你需要注意:在查看測試結果時,方法名稱 test_the_application_returns_a_successful_response()
如何變為可讀文本,只需將下劃線符號替換為空格即可。
tests/Unit/ExampleTest.php:
class ExampleTest extends TestCase{ public function test_that_true_is_true() { $this->assertTrue(true); } }
這樣的程式碼看起來讓人感覺毫無意義,檢查結果為 true 很有必要嗎?在後面片段中,我們將具體討論單元測試。現在,你只需要了解每次測試中通常發生的情況。
-
tests/
資料夾中的每個測試檔案都是一個PHP 類,擴展了PHPUnit 的TestCase - 在每個類別中,你可以建立多個方法,通常一種方法用於一種情況進行測試
- 每個方法內部都有三個動作:準備情況,然後動作,然後檢查(斷言)結果是否符合預期
從結構上講,這就是你需要知道的全部內容,其他一切都取決於你要測試的確切內容。
要產生一個空的測試類,只需執行以下命令:
php artisan make:test HomepageTest
它會產生檔案tests/Feature/HomepageTest.php
:
class HomepageTest extends TestCase{ // Replace this method with your own ones public function test_example() { $response = $this->get('/'); $response->assertStatus(200); } }
如果測試失敗怎麼辦?
讓我向你展示如果測試斷言沒有回傳預期結果會發生什麼。
讓我們將範例測試編輯為:
class ExampleTest extends TestCase { public function test_the_application_returns_a_successful_response() { $response = $this->get('/non-existing-url'); $response->assertStatus(200); } } class ExampleTest extends TestCase { public function test_that_true_is_false() { $this->assertTrue(false); } }
現在,如果我們再次執行php artisan test
:
FAIL Tests\Unit\ExampleTest ⨯ that true is true FAIL Tests\Feature\ExampleTest ⨯ the application returns a successful response --- • Tests\Unit\ExampleTest > that true is true Failed asserting that false is true. at tests/Unit/ExampleTest.php:16 12▕ * @return void 13▕ */ 14▕ public function test_that_true_is_true() 15▕ { ➜ 16▕ $this->assertTrue(false); 17▕ } 18▕ } 19▕ • Tests\Feature\ExampleTest > the application returns a successful response Expected response status code [200] but received 404. Failed asserting that 200 is identical to 404. at tests/Feature/ExampleTest.php:19 15▕ public function test_the_application_returns_a_successful_response() 16▕ { 17▕ $response = $this->get('/non-existing-url'); 18▕ ➜ 19▕ $response->assertStatus(200); 20▕ } 21▕ } 22▕ Tests: 2 failed Time: 0.11s
如你所見,有兩個語句標記為FAIL,下面有解釋,箭頭指向斷言失敗的確切測試行。所以這就是錯誤的顯示方式。這非常的方便,不是嗎?
简单示例:注册表单
让我们来看看一个现实生活中常见的例子。假设你有一个表单,你需要测试各种情况:检查是否填充无效数据是否失败,检查是否输入正确输入成功等。
你不一定知道,其实官方的 Laravel Breeze 入门套件附带了 内部功能测试?现在,让我们从那里看几个例子:
tests/Feature/RegistrationTest.php
use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class RegistrationTest extends TestCase { use RefreshDatabase; public function test_registration_screen_can_be_rendered() { $response = $this->get('/register'); $response->assertStatus(200); } public function test_new_users_can_register() { $response = $this->post('/register', [ 'name' => 'Test User', 'email' => 'test@example.com', 'password' => 'password', 'password_confirmation' => 'password', ]); $this->assertAuthenticated(); $response->assertRedirect(RouteServiceProvider::HOME); } }
在这里,我们在一个类中有两个测试,因为它们都与注册表相关:一个是检查表单是否正确加载了,另一个是检查提交是否正常。
我们来熟悉另外两个检查结果的方法,另外两个断言: $this->assertAuthenticated()
和 $response->assertRedirect()
。 你可以查看 PHPUnit and Laravel Response 官方文档中所有可用的断言。请记住,一些一般的断言发生在 $this
对象上,而另一些检查则来自于路由调用的特定 $response
语句。
另一件重要的事情是 use RefreshDatabase;
语句,使用这个 trait,包含在这个类的上方。当你的测试操作可能会影响数据库时,需要使用它,例如在本例中,注册会在 users
数据库表中添加一个新条目。为此,你需要创建一个单独的测试数据库,该数据库将会在每次测试中使用 php artisan migrate:fresh
命令时被刷新。
你有两个选择:物理上创建一个单独的数据库,或者使用内存中的 SQLite 数据库。它都在 Laravel 默认提供的文件 phpunit.xml
中配置。具体来说, 你需要这部分:
<php> <env name="APP_ENV" value="testing"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_DRIVER" value="array"/> <!-- <env name="DB_CONNECTION" value="sqlite"/> --> <!-- <env name="DB_DATABASE" value=":memory:"/> --> <env name="MAIL_MAILER" value="array"/> <env name="QUEUE_CONNECTION" value="sync"/> <env name="SESSION_DRIVER" value="array"/> <env name="TELESCOPE_ENABLED" value="false"/> </php>
看到被注释掉的 DB_CONNECTION
和 DB_DATABASE
了吗?如果你的服务器上有 SQLite,最简单的操作就是取消注释这些行,你的测试将在该内存数据库上运行。
在本次测试中,我们断言用户通过了身份验证,并被重定向到正确的首页,但我们也可以测试数据库中真实的数据。
除此代码之外:
$this->assertAuthenticated(); $response->assertRedirect(RouteServiceProvider::HOME);
我们也可以使用 Database Testing assertions 并执行以下操作:
$this->assertDatabaseCount('users', 1); // 或者... $this->assertDatabaseHas('users', [ 'email' => 'test@example.com', ]);
另外一个真实示例:登录表单
让我们看看另外一个来自 Laravel Breeze 的测试。
tests/Feature/AuthenticationTest.php:
class AuthenticationTest extends TestCase { use RefreshDatabase; public function test_login_screen_can_be_rendered() { $response = $this->get('/login'); $response->assertStatus(200); } public function test_users_can_authenticate_using_the_login_screen() { $user = User::factory()->create(); $response = $this->post('/login', [ 'email' => $user->email, 'password' => 'password', ]); $this->assertAuthenticated(); $response->assertRedirect(RouteServiceProvider::HOME); } public function test_users_can_not_authenticate_with_invalid_password() { $user = User::factory()->create(); $this->post('/login', [ 'email' => $user->email, 'password' => 'wrong-password', ]); $this->assertGuest(); } }
这是关于登录表单的例子。他的逻辑和注册差不多吧?但不一样的是使用了三个方法而不是两个,所以这是一个测试好的和坏的场景的例子。所以,他们共同的逻辑是你应该测试的两种情况:什么时候顺利,什么时候失败。
此外,你在这个测试中看到的是 Database 工厂类 的使用:Laravel 创建了一个假用户(再次, 在你的测试数据库刷新) 上,然后尝试使用正确或不正确的凭据登录。
同样,Laravel 为 User
模型生成带有假数据的默认工厂,开箱即用。
database/factories/UserFactory.php:
class UserFactory extends Factory { public function definition() { return [ 'name' => $this->faker->name(), 'email' => $this->faker->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), ]; } }
看,有多少东西是 Laravel 本身提供的,所以我们很容易开始测试。
因此,如果我们在安装 Laravel Breeze 后运行 php artisan test
, 我们应该会看到如下内容:
PASS Tests\Unit\ExampleTest ✓ that true is true PASS Tests\Feature\Auth\AuthenticationTest ✓ login screen can be rendered ✓ users can authenticate using the login screen ✓ users can not authenticate with invalid password PASS Tests\Feature\Auth\EmailVerificationTest ✓ email verification screen can be rendered ✓ email can be verified ✓ email is not verified with invalid hash PASS Tests\Feature\Auth\PasswordConfirmationTest ✓ confirm password screen can be rendered ✓ password can be confirmed ✓ password is not confirmed with invalid password PASS Tests\Feature\Auth\PasswordResetTest ✓ reset password link screen can be rendered ✓ reset password link can be requested ✓ reset password screen can be rendered ✓ password can be reset with valid token PASS Tests\Feature\Auth\RegistrationTest ✓ registration screen can be rendered ✓ new users can register PASS Tests\Feature\ExampleTest ✓ the application returns a successful response Tests: 17 passed Time: 0.61s
功能测试 VS 单元测试 VS 其他
你已经看到了 tests/Feature
和 tests/Unit
子文件夹。两者之间有什么区别?答案有点“哲学”。
从测试的全局视角来看,在 Laravel/PHP 生态系统之外,有不同类型的自动化测试。你可以找到以下术语:
- 单元测试
- 功能测试
- 集成测试
- 功能测试
- 端到端测试
- 验收测试
- 烟雾测试
- 其他
这听起来很复杂,而且这些测试类型之间的实际差异有时是模糊的。这就是为什么 Laravel 简化了所有这些令人困惑的术语并将它们分为两类:单元测试/功能测试。
简而言之,功能测试尝试运行应用程序的实际功能:获取 URL、调用 API、模拟填写表单等确切行为。功能测试通常执行与任何项目用户在现实生活中手动执行的相同或相似的事情。
单元测试有两个含义。通常,你可能会发现任何自动化测试都称为「单元测试」,而整个过程可能称为「单元测试」。但是在功能与单元的上下文中,这个过程是关于单独测试代码的特定非公共单元。例如,你有一些 Laravel 类,它有一个计算某些东西的方法,比如带有参数的订单的总价格。因此,你的单元测试将断言该方法(代码单元)是否返回了具有不同参数的正确结果。
要生成单元测试,你需要添加一个标志:
php artisan make:test OrderPriceTest --unit
生成的代码与 Laravel 的默认单元测试相同:
class OrderPriceTest extends TestCase { public function test_example() { $this->assertTrue(true); } }
如你所见,没有 RefreshDatabase
行为的定义,这是单元测试最常见的定义之一:它不涉及数据库,它像一个「黑匣子」一样工作,与正在运行的应用程序隔离。
你可以尝试模仿我之前提到的示例,假设我们有一个服务类 OrderPrice
。
app/Services/OrderPriceService.php:
class OrderPriceService{ public function calculatePrice($productId, $quantity, $tax = 0.0) { // 某种计算逻辑 } }
然后,单元测试可能看起来像这样:
class OrderPriceTest extends TestCase{ public function test_single_product_no_taxes() { $product = Product::factory()->create(); // 生成假的产品数据 $price = (new OrderPriceService())->calculatePrice($product->id, 1); $this->assertEquals(1, $price); } public function test_single_product_with_taxes() { $price = (new OrderPriceService())->calculatePrice($product->id, 1, 20); $this->assertEquals(1.2, $price); } // 更多的参数和案例 }
从我个人对 Laravel 项目的经验而言,绝大多数测试是功能测试,而不是单元测试。首先,你需要测试你的应用程序是否正常工作,以及真实用户使用它的方式。
接下来,如果你有可以定义为单元的特殊计算或逻辑,或带有一些参数,你可以专门为此创建单元测试。
有时候,编写测试需要更改代码本身,并将其重构为更「可测试的」:将单元分离为特殊的类或方法。
何时/如何运行测试?
php artisan test
命令的实际用途是什么,我们应该在什么时候运行它?
什么时候运行测试,在开发过程中并没有固定的时间节点或说法,具体取决于你公司的工作流程。通常情况下,在我们将最新的代码更改推送到代码仓库之前,你需要确保所有测试都是「绿色的」(意味着没有错误)。
因此,当你在本地编写代码,在你觉得自己已经完成了你的任务时,你需要运行测试,用来确保你没有破坏任何东西。请记住,你的代码可能不仅会在你自己编写的代码逻辑中导致错误,而且还会无意中破坏其他人很久以前编写的代码中的其他行为。
如果我们更进一步,可以自动化的完成很多事情。如使用各种 CI/CD 工具,你可以指定在有人将更改推送到特定 Git 分支时或在将代码合并到生产分支之前执行的测试。最简单的工作流程是使用 Github Actions,在这里,我提供了 一个单独的视频 演示它。
你应该测试什么?
关于所谓的「测试覆盖率」应该覆盖到多大的范围的争议,一直以来,有多种意见:你应该测试每个页面上的每个操作和每个可能的案例,还是只将你的工作限制在最重要的部分。
事实上,这就是我同意人们指责自动化测试花费更多时间而不是带来实际收益观点的地方。如果你为每个细节编写测试,这种情况就可能出现。也就是说,你的项目可能需要思考这个问题:「代码中潜在的错误会给你带来多大的成本或代价」。
换句话说,你需要通过“如果此代码失败会发生什么?”这个问题来确定你的测试工作的优先级。如果你的支付系统存在错误,这将直接影响业务。如果你的角色/权限功能被破坏,那这将是一个巨大的安全问题。
我喜欢 Matt Stauffer 在一次会议上的措辞:「你需要先测试这些东西,如果它们失败了,你就会被解雇」。当然,这有点夸张,但你明白了:首先测试重要的事情。然后是其他功能,如果你有时间的话。
PEST:PHPUnit 的新流行替代品
以上所有示例均基于默认的 Laravel 测试工具:PHPUnit。但多年来,生态系统中出现了其他工具,最新流行的工具之一是 PEST。由 Laravel 官方员工 Nuno Maduro 创建,它的目标是简化语法,从而更快地编写测试代码。
在底层实现上,它基于 PHPUnit 运行;作为一个附属扩展,它只是试图最小化 PHPUnit 代码的一些默认重复部分。
让我们来看一个例子。还记得 Laravel 中默认的功能测试类吗?就如下面这段代码:
namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ExampleTest extends TestCase { public function test_the_application_returns_a_successful_response() { $response = $this->get('/'); $response->assertStatus(200); } }
让我们使用 PEST 来实现同样的测试,实现后的代码如下:
test('the application returns a successful response')->get('/')->assertStatus(200);
是的,一行代码,就是这样。因此,PEST 的目标是解决以下问题:
- 为一切创建类和方法;
- 扩展测试用例;
- 将所有操作放在一行代码上 – 在 PEST 中,你可以使用链式操作把不同动作串联起来。
要在 Laravel 中生成 PEST 测试,你需要指定一个附加标志:
php artisan make:test HomepageTest --pest
在撰写本文时,PEST 在 Laravel 开发人员中相当流行,但是除了众所周知的 PHPUnit 之外,是否使用这个额外的工具并学习它的语法是你个人的喜好。
因此,这就是你需要了解的有关自动化测试基础知识的全部内容。从这里开始,你可以选择创建哪些测试以及如何在你的项目中运行它们。
原文地址:https://laravel-news.com/how-to-start-testing
译文地址:https://learnku.com/laravel/t/67381
更多编程相关知识,请访问:编程教学!!
以上是Laravel如何進行自動化測試? PHPUnit和PEST的範例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

随着软件开发的迅速发展,自动化测试在开发过程中扮演着越来越重要的角色。相较于人工测试,自动化测试可以提高测试的效率和准确性,减少交付的时间和成本。因此,掌握自动化测试变得非常必要。Go语言是一门现代化的、高效的编程语言,由于其特有的并发模型、内存管理和垃圾回收机制,使得它在Web应用、网络编程、大规模并发、分布式系统等领域有着广泛的应用。而在自动化测试方面,

译者 | 陈峻审校 | 孙淑娟近年来,自动化测试已经发生了重大的迭代。它在很大程度上协助QA团队减少了人为错误的可能。虽然目前有许多工具可以被用于自动化测试,但合适的工具一直是自动化测试成败与否的关键。同时,随着人工智能、机器学习和神经网络在各个领域的广泛运用,面向人工智能的自动化测试也需要通过合适的工具,来承担重复性的工作,以节省项目团队宝贵的时间,去执行更加复杂和关键的任务。下面,我将和您深入探讨面向未来的AI自动化测试工具。什么是人工智能(AI)自动化测试?AI自动化测试意味着现有的软件

随着互联网技术的快速发展,微服务架构也越来越被广泛应用。使用微服务架构可以有效避免单体应用的复杂度和代码耦合,提高应用的可扩展性和可维护性。然而,与单体应用不同,在微服务架构中,服务数量庞大,每个服务都需要进行自动化测试和部署,以确保服务的质量和可靠性。本文将针对微服务架构中如何处理服务的自动化测试和部署进行探讨。一、微服务架构中的自动化测试自动化测试是保证

Gin是一个用Golang编写的Web框架,它具有高效、轻量、灵活等优点,性能相对较高,并且易于使用。在Gin框架开发中,API文档和自动化测试十分重要。本文将深入探讨Gin框架中的API文档和自动化测试。一、API文档API文档用于记录所有API接口的详细信息,方便其他开发人员使用和理解。Gin框架提供了多种API文档工具,包括Swagger、GoSwa

随着互联网企业的不断壮大,软件开发的复杂性越来越高,测试工作也越来越重要。为了保证程序的正确性和稳定性,必须进行各种类型的测试。其中自动化测试是一种非常重要的方式,它可以提高测试工作效率,减少错误率,并且允许重复执行测试用例以便早发现问题,但是在实际操作过程中,我们也会遇到种种的问题,比如测试工具的选择、测试用例的编写以及测试环境的搭建等问题。go-zero

随着Vue技术的不断发展,越来越多的企业开始使用Vue来开发前端应用。但是,在开发过程中,如何保证代码的质量和稳定性呢?这时候,自动化测试就成为了必不可少的一环。本文将介绍Vue项目中的自动化测试工具及其使用方法,帮助开发者更好地进行测试和验证。一、自动化测试的概述自动化测试是指使用自动化工具来执行测试方案,并发布测试结果。与手动测试相比,自动化测试可以更快

随着Web应用程序的普及和互联网的飞速发展,WebUI测试已经成为软件开发过程中不可忽视的一环。自动化WebUI测试是提高测试效率,缩短项目周期的有效手段。本文将介绍利用PHPWebDriver实现自动化WebUI测试的最佳实践。一、什么是PHPWebDriver?PHPWebDriver是一个基于WebBrowserAutomationA

UniApp是一款跨平台的应用开发框架,可以快速开发出同时适配多个平台的应用程序。在开发过程中,我们经常需要进行自动化测试和性能监控来保证应用的质量和性能。本文将为大家介绍UniApp如何配置和使用自动化测试与性能监控的工具。一、自动化测试配置与使用指南下载并安装必要的工具UniApp的自动化测试依赖于Node.js和WebdriverIO。首先,我们需要下


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

Dreamweaver Mac版
視覺化網頁開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。