大多数人都知道测试您的网站是个好主意,但一段时间后测试可能会变得乏味。如果很多测试过程可以自动化,这样你就不必一次又一次地手动检查每个函数,以确保它在更新代码后仍然有效,那会怎么样?这就是单元测试的用武之地,以自动化测试过程。
单元测试使修改代码变得更容易,最重要的是更安全,因为它可以捕获新代码中可能引入的行为中的任何异常(即错误)。在本文中,您将学习使用 PHPUnit 进行单元测试的绝对基础知识,以及开始使用它是多么容易,因为我将指导您完成编写第一个测试的过程。
在开始编写第一个单元测试之前,您需要安装 PHPUnit。它可以使用PEAR安装程序轻松安装
编写您的第一个测试
现在是时候亲自动手编写您的第一个测试了!首先,你需要测试一些东西,所以在第一个例子中,我写了一个非常简单的PHP类来表示一个用户:
<?php class User { protected $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function talk() { return "Hello world!"; } }
假设您希望确保用户始终打招呼;例如,如果她突然开始像猫一样喵喵叫,那将是毁灭性的!
为此,您需要创建一个新的测试类,我将其任意命名为 .你怎么称呼你的测试类并不重要,但通常以你正在测试的类命名它们是一个好主意。UserTest
要创建测试类,您需要包含要测试的类以及 PHPUnit 的自动加载功能。然后定义扩展的测试类。PHPUnit_Framework_TestCase
<?php require_once "PHPUnit/Autoload.php"; require_once "User.php"; class UserTest extends PHPUnit_Framework_TestCase { }
这是您将在其中编写测试的类,每个测试都有自己的方法。
中定义的方法正是您假设的,它断言某物是否相等。由于 是 的子类,因此可以将其与 一起使用。assertEquals()
PHPUnit_Framework_TestCase
UserTest
PHPUnit_Framework_TestCase
$this
若要确保用户说出适当的问候语,请编写以下方法:
<?php ... class UserTest extends PHPUnit_Framework_TestCase { // test the talk method public function testTalk() { // make an instance of the user $user = new User(); // use assertEquals to ensure the greeting is what you $expected = "Hello world!"; $actual = $user->talk(); $this->assertEquals($expected, $actual); } }
设置和拆卸
需要在每种测试方法中设置新用户可能会变得非常乏味。这就是 PHPUnit 的灯具可以提供帮助的地方。夹具是指设置特定状态,每次测试后状态都会重置回原样。这是如何工作的?
假设你有你的对象,并且你重写了继承的方法:$user
setUp()
<?php ... class UserTest extends PHPUnit_Framework_TestCase { protected $user; ... protected function setUp() { $this->user = new User(); $this->user->setName("Tom"); } }
在这里,你已实例化了用户并将其名称设置为 Tom。
完成所有测试后,您可能希望取消设置用户;为此,您可以重写该方法:tearDown()
<?php ... class UserTest extends PHPUnit_Framework_TestCase { ... protected function tearDown() { unset($this->user); } ... }
PHPUnit 在每次测试之前和之后都会调用 and 方法,因此您可以跳过在测试方法中实例化用户。 现在变为:setUp()
tearDown()
testTalk()
<?php ... class UserTest extends PHPUnit_Framework_TestCase { ... public function testTalk() { $expected = "Hello world!"; $actual = $this->user->talk(); $this->assertEquals($expected, $actual); } }
运行测试
现在你已经有一个定义所有测试的测试类,运行它们不是很好吗?如果您已成功安装所有内容,则应该能够简单地从终端运行测试。
michelle@testbed:~$ phpunit UnitTest UserTest.php
PHPUnit 3.6.3 by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 5.75Mb
OK (1 test, 1 assertion)
祝贺!您现在已经使用 PHPUnit 编写并运行了您的第一个单元测试!
你看到那里的小点了吗?对于每次测试运行,都会有一个字符指示结果。字符如下:
- .– 测试成功时打印。
- F – 断言失败时打印。
- E – 在运行测试时发生错误时打印。
- S – 跳过测试时打印。
- I – 当测试标记为不完整时打印。
现在,您需要担心的两个最重要的问题是点和 F,因为它们表明您的测试是成功还是失败。
当测试失败时
那么,当测试失败时会发生什么?让我们改变一下,这样他们实际上会说一些完全出乎意料的话,比如“blubb”。User
<?php class User { ... public function talk() { return "blubb"; } }
现在像以前一样运行测试。
michelle@testbed:~$ phpunit UnitTest UserTest.php
PHPUnit 3.6.3 by Sebastian Bergmann.
F
Time: 0 seconds, Memory: 5.75Mb
There was 1 failure:
1) UserTest::testTalk
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-Hello World!
+blubb
/PHPUnit introduction/tests/UserTest.php:23
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
如您所见,F 符号表示失败。还有关于失败的更多信息,你可以看到它失败了,断言两个字符串相等;它期待“Hello World!”,但得到了“blubb”。
总结
在本文中,你发现开始进行单元测试并不难。基础知识非常简单。然而,单元测试远比我们看到的要多得多。这个简单的测试情况应该足以让你开始编写自己的测试,但请尝试扩展它,出现错误并未通过测试。尝试扩展类并为其编写其他测试。添加 、 或 属性怎么样?User
height
hair_color
birthday
我可以提供一些有用的提示,这些提示将在此过程中为您提供帮助:
- 尝试在终端中调用,看看你可以用 PHPUnit 做什么。
phpunit --help
- 如果你想知道如何测试一些特定的东西,PHPUnit手册实际上非常好。我简要提到了夹具,手册中有完整的描述。
- 当您刚开始时,涵盖断言的手册部分真的很震撼。请务必检查一下。
如果要从本文中下载测试代码进行试验,可以在 GitHub 上随心所欲地使用它。
我希望本教程能帮助您开始使用 PHPUnit。尝试一下,从错误中吸取教训,不要害怕提出任何问题,最重要的是玩得开心!
编者注 2012 年 10 月 19 日:GitHub 上提供的随附代码已更新为使用 Composer 下载 PHPUnit 依赖项。require 语句已更改为调用 vendor/autoload.php 来采购自动加载程序。可以通过导航到 tests 目录并调用 .. 来运行测试。/vendor/bin/phpunit 单元测试UserTest.php。
发表评论 取消回复