在Symfony框架中,单元测试是保证代码质量的重要手段。本文将通过一个具体的例子,展示如何在Symfony项目中为“用户”实体编写单元测试。这个用户实体代表了在为Taft College创建的请愿系统中的一个用户。
在Symfony项目的任何部分,测试用例都应该存储在“tests”文件夹下。此外,也可以在“phpunit.xml.dist”文件的“testsuite”标签内指定这个文件夹。对于实体(Entity),一个合适的文件夹路径是:
tests\AppBundle\Entity
在案例中,在上述文件夹下创建了名为“UserTest.php”的文件。
所有的PHPUnit测试类都应该扩展“PHPUnit\Framework\TestCase”。因此,一个最简的文件将包含以下内容:
namespace tests\AppBundle\Entity;
use AppBundle\Entity\User;
use PHPUnit\Framework\TestCase;
class UserTest extends TestCase {
public function testUserCreate() {
$user = new User();
// 创建用户对象。
...
}
}
上述代码简单地创建了一个用户对象,并没有做其他事情。因此,需要查看User类有哪些方法,并将每个方法(如果可能的话)添加到测试用例中。
接下来,让测试setUserName方法,并使用getUserName来验证,所以添加了如下的测试代码:
public function testUserCreate() {
$user = new User();
// 创建用户对象。
$user->setUserName("Name");
$this->assertEquals("Name", $user->getUserName());
}
接下来,让测试它以确保一切正常,并且正在正确的道路上。
在Symfony的当前版本中,需要使用以下命令从Symfony项目的顶级目录运行PHPUnit:
./vendor/bin/phpunit
这个命令本身并不是很有用。建议使用覆盖率,并且只指定创建的单个测试用例,因为只想验证这个用例是否正常工作。如果出现太多错误/调试消息,将会很难进行故障排除。所以,要运行上述测试用例文件并查看覆盖率,请使用以下命令:
./vendor/bin/phpunit --coverage-text tests/AppBundle/Entity/UserTest.php
当上述命令正常运行时,它会显示PHPUnit的版本、测试/断言的数量,并且以彩色显示覆盖率(绿色是好的)。以下是正常结果的截图:
这个结果表明,User类的15个方法中有3个被调用了,这并不是很多。对于测试用例,需要尽可能地测试100%的方法。
总共创建了两个测试用例,因为用户需要在应用程序中添加签名,将这个功能分割成第二个测试用例来添加签名到用户是很重要的。这仍然测试了User功能。
以下是创建用户的完整测试用例:
public function testUserCreate() {
$user = new User();
// 创建用户对象。
$user->setUserName("Name");
$user->setUserType("Advisor");
$user->setFosUsername("FOS");
$user->setDivision("DIV");
$user->setDivAlt("DIV_ALT");
$sig = new Signature();
// 创建一个签名。
$sig->setSigType("Advisor_Submit");
$date = date("Y-m-d H:i:s", strtotime('2018-12-31 09:20:35'));
$sig->setSigDate($date);
$user->addSignature($sig);
$this->assertEquals("Name", $user->getUserName());
$this->assertEquals("Advisor", $user->getUserType());
$this->assertEquals("FOS", $user->getFosUsername());
$this->assertEquals("DIV", $user->getDivision());
$this->assertEquals("DIV_ALT", $user->getDivAlt());
$this->assertEquals(null, $user->getUserId());
$sigCollection = $user->getUSignatures();
$this->assertEquals($date, $sigCollection->last()->getSigDate());
$user->removeUSignature($sig);
// 移除签名。
$sigCollection = $user->getUSignatures();
$this->assertEquals(true, $sigCollection->isEmpty());
}
以下是测试向用户添加签名的完整测试用例:
public function testAddSignature() {
$user = new User();
// 创建用户对象。
$user->setUserType("Advisor");
$sig = new Signature();
$sig->setSigType("Advisor_Submit");
$date = date("Y-m-d H:i:s", strtotime('2018-12-31 09:20:35'));
$sig->setSigDate($date);
$sig->setRecommend("yes");
$sig->setSigExplain("sig_explanation");
$sig->setUser($user);
$sig->setNotes("some_Notes");
$user->addSignature($sig);
$sigs = $user->getUSignatures();
$this->assertNotEmpty($sigs);
foreach ($sigs as $s) {
$this->assertEquals("Advisor_Submit", $s->getSigType());
$this->assertEquals($date, $s->getSigDate());
$this->assertEquals("yes", $s->getRecommend());
$this->assertEquals("sig_explanation", $s->getSigExplain());
$this->assertEquals($user, $s->getUser());
$this->assertEquals("some_Notes", $s->getNotes());
$this->assertEquals(null, $s->getSigId());
}
$sig->removeUser($user);
$s2 = $user->getUSignatures();
$this->assertEmpty($s2);
}
注意:当创建添加签名的测试用例时,意识到不能简单地使用setUser(null)方法来移除一个用户;相反,必须添加一个名为“removeUser”的方法来正确地移除用户。有时,当在审查代码并编写测试用例时,可能需要这样做。