PHP 开发入门自动化测试历程(二)
刻意练习,坚持
在上篇文章中,对 PHPUnit
已经有了基础的认识后,就可以回归到真实的场景中,在 Laravel
框架中为应用程序编写自动化测试代码。
Laravel 测试
Laravel
官方文档中,明确写出了其对测试的良好支持,默认就支持用 PHPUnit
来做测试。这个支持可能表现在这两个地方:
- 默认引用了
phpunit/phpunit
包 - 优雅扩展了
PHPUnit
了解 Laravel
测试结构
要在框架中编写测试,首先得了解框架和测试代码的结构。
在一个 Laravel
应用根目录下,默认存在 如下结构:
tests
目录(编写测试的地方)Feature
目录(存放功能测试)Unit
目录(存放单元测试)CreateApplication.php
文件(用于初始化框架应用)TestCase
文件(所有测试类需要继承的抽象类,内部引用了CreateApplication
)
phpunit.xml
文件(指导phpunit
运行 )。
因此,当安装好了 PHPUnit
,并在根目录下执行 phpunit
命令,会自动搜索 phpunit.xml
文件,然后根据文件里的配置信息运行默认的测试。
如果没有安装 PHPUnit
,因为默认引用了 phpunit/phpunit
包,还可以使用 ./vendor/bin/phpunit
运行测试。
不纠结功能测试与单元测试
在上一篇文章中,就提到了不要过分纠结功能测试、单元测试这些概念的定义。但现在遇到了,就给出自己简单的认知(不一定正确,主要是让自己理解),以接口开发为例:
- 针对某个具体接口或多个接口组合的测试,可以称为 “功能测试”
- 每个接口中可能调用多个独立方法,针对这些方法的测试,可以理解为 “单元测试”
具体编写测试
在有了上述的基础后,就可以开始编写自己的测试代码了,不要期望一口气写出多么优雅、完善的测试代码,最重要的是 坚持 刻意练习,在编写的过程中不断调整总结自己的经验出来。以一个简单的保存接口为例:
存在一个接口 xxx/article
用于新建文章,那就可以为此创建一个功能测试: php artisan make:test CreateArticleTest
,内容如下:
<?php
namespace Tests\Feature\Credits;
use Tests\TestCase;
class CreateArticleTest extends TestCase
{
// 接口URI
protected $createArticleUri = 'xxx/article';
/** @test 测试创建文章要求必填标题*/
public function create_article_require_title()
{
// 请求接口,并断言接口响应与返回码
$this->json('POST', $this->createArticleUri, ['title' => null])
->assertStatus(200)
->assertJson(['code' => 'xxxx']);
}
}
假设接口内部,会验证文章是否重名,通常我们会为此编写一个独立方法,此时就需要创建一个单元测试: php artisan make:test ArticleTest --unit
,内容如下:
<?php
namespace Tests\Unit;
use Tests\TestCase;
class ArticleTest extends TestCase
{
/** @test 测试可以判断文章是否重名*/
public function can_konw_title_is_repeat()
{
$articleOne = factory(Article::class)->create(['title' => '标题1']);
$articleTwo = factory(Article::class)->make(['title' => '标题1']);
$result = $articleTwo->isRepeat();
$this->assertTrue($result);
}
}
总结
上面列举了一个非常简单的测试,这里并不会详细的介绍 Laravel
框架里测试的方法,建议阅读官方文档,后面会列出参考链接。
要再次强调,对于开发而言,写这些测试代码的难度并不高,关键还是要坚持写、刻意练习、不断总结,入门都不是问题。
在养成编写测试代码的习惯后,遇到的测试场景也会越来越多,思维也会更加完善,代码质量随着会更加有保障。
Laravel
网站有个文档 《TDD 构建 Laravel 论坛笔记》,是很不错的入门指引,有条件也可以购买网站上的 L07 Laravel 教程 - Laravel TDD ,这也是很好的教程。
在入门的过程中,自己也总结了一些点:
注意直接使用
PHPUnit
与在Laravel
中使用的差异
因为Laravel
扩展了PHPUnit
,因此某些方法是原生PHPUnit
中不存在的,只在Laravel
中可以使用,不过这些扩展的内容,使用起来确实会更加优雅。使用
Laravel
数据库事务,清理测试数据Laravel
提供了DatabaseTransaction
的Trait
,只要在测试类中引入了。就会将每个测试用例包含在事务中, 及时清除数据库里的测试数据。暴露异常,便于定位问题
对于接口Laravel
默认会进行异常处理,这在测试过程中是不利于调试的,可以在测试方法中使用:// 不处理异常 $this->withoutExceptionHandling(); // 处理异常 $this->withExceptionHandling();
使用
Laravel
模型工厂快捷造数据
很多测试的执行,都需要依赖很多数据,通过Laravel
的模型工厂,可以很快捷的构造需要的数据。
参考
后续历程
本作品采用《CC 协议》,转载必须注明作者和本文链接