首先测试是一个比较大的概念,今天我们只讨论单元测试。
作为开发保证自己编写代码的正确性是最基本的,当我们向QA提测前如果做好自测是最基本的,而如何漂亮的做好自测?如何快速的检查某个函数边界条件的正确性?单元测试可以帮我们做到,而做到的还不止一点点,。试想一下,如果经历无Bug上线这样美好的事儿,那于我们来讲是多么美好呢!总之,去编写单元测试吧,让我们更加自信的去提测,一切都会变得美好!
而美好的愿望总是会遇到一些阻碍,比如在国内很少有编写单元测试这样的氛围,而也很少存在那些主动的开发人员将单元测试普及开来,导致这样美好的愿望阻碍重重。
如果你们的项目有用到Laravel这样如此Graceful的框架,那么编写单元测试将会非常容易,而这也是今天讨论的重点。
更多关于PHP测试相关的内容,可以看我之前的这篇文章PHP与测试
Laravel的PHPUnit
我们编写的所有测试用例将会存放在Laravel框架下的tests目录下。默认情况下,Laravel为我们准备了两个文件TestCase.php和ExampleTest.php,TestCase.php将作为我们编写的测试用例类的基类,继承了TestCase.php后,我们将可以很方便的使用Laravel以PHPUnit为基础为我们封装的各种方法,使得我们的测试方便至极!真的是方便至极!
比如ExampleTest.php : 就是用来测试那个非常经典的Laravel默认页
<?php
//...省略
public function testBasicExample()
{
$this->visit('/')
->see('Laravel 5');
}
//...省略
- $this->visit(‘/’); : 模拟一个http请求,访问路由/
- $this->see(‘Laravel 5’); : 检查返回的html源代码中是否存在Laravel 5这个字符串
除了tests目录下的TestCase.php和ExampleTest.php之外还有一个很重要的PHPUnit配置文件,即phpunit.xml,既然是配置文件,则在其中定义了一些这样的事儿,比如以Test.php为结尾的文件将会被作为测试用例执行,设定Laravel的ENV为testing等等,基本上默认的phpunit.xml是不需要改动的,可以直接拿来用。
好,上面简单的做一下介绍,下面让我们正式讨论如何在Laravel中编写测试用例。
Get Start
安装phpunit命令(可选)
我们会需要phpunit的全局可执行命令,作为我们测试的命令。不过这个步骤是可选的,原因在于你会发现vendor/bin目录下存在这个命令,所以如果不全局安装是可以直接使用这个命令的。
具体的安装步骤:
//使用composer全局安装phpunit,后面的版本号参考composer.json中的phpunit版本,比如我的是4.8.27
composer global require phpunit/phpunit 4.8.27
//打开vim ~/.profile,追加如下环境变量
export PATH=~/.composer/vendor/bin:$PATH
source ~/.profile
//测试是否安装成功
phpunit --version
修改TestCase.php
修改你的$baseUrl为你的可执行的链接,一定要保证你的机器是可以访问到此链接的哈,不确定的话,可以ping一下。
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class TestCase extends Illuminate\Foundation\Testing\TestCase
{
/**
* The base URL to use while testing the application.
* @var string
*/
protected $baseUrl = 'http://yourhost.com';
public function setUp()
{
parent::setUp();
}
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
return $app;
}
}
执行测试用例
既然已经准备OK了,那么就可以在项目根目录下执行phpunit命令了,如果能看到下面的一幕则我们已经完成了测试的第一步!恭喜!
➜ laravel_project git:(master) phpunit
PHPUnit 4.8.27 by Sebastian Bergmann and contributors.
..
Time: 361 ms, Memory: 13.75MB
OK (2 tests, 2 assertions)
编写我们的第一个测试
假如我的项目中存在一个API接口,访问路由为/api/username,返回的数据结构为:
{
code: 0,
message: "操作成功。",
data: {
"name" : "xuwenzhi"
}
}
此时我可以通过命令来创建一个测试用例(测试用例的名称一定要Test.php结尾,这个规则是在phpunit.xml中定义的)
php artisan make:test UserNameTest
此时,tests目录下会出现我们新建的测试用例UserNameTest.php,打开它,编辑如下
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class UserNameTest extends TestCase
{
protected $route = '/api/username';
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->json('GET', $this->route);
$this->assertResponseOk();
$this->assertResponseStatus(200);
$this->seeJson([
'code' => 0,
'message' => '操作成功',
'data' => [
'name' => 'xuwenzhi'
],
])->seeJsonStructure([
'code',
'data' => [
'name',
],
'message',
]);
$content = $this->decodeResponseJson();//将返回结果做json_decode()
print_r($content);
}
}
执行如下命令,即可单独测试该用例
phpunit tests/UserNameTest.php
其他补充
Laravel提供的API
上面我们写了一个简单的测试用例,其中我们注意到$this->json($method, $uri, array $data = [], array $headers = [])方法,调用此方法Laravel将会自动为我们发起一个HTTP请求,对于请求方式GET/POST/其他则通过第一个参数指定,第二个参数为路由,第三个参数为请求携带的参数,第四个参数为headers相关。
对于这样的函数还有很多,选择性也很多,比如:
//发起任意类型的请求
$this->call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null);
//发起GET请求
$this->get($uri, array $headers = []);
//发起POST请求
$this->post($uri, array $data = [], array $headers = []);
//同样的,任何一个HTTP METHOD请求均可以这样的方式发起。
//发起针对json API的请求(即返回数据为json类型)
$this->json('GET', '/api/agent/config?city_id=110000');
//打印接口返回的数据
$this->dump();
//获取接口响应内容
$response = $this->call('GET', $this->route);
$content = $response->getContent()//$content即为接口返回数据
Laravel提供的Asserting(断言)
什么叫断言?也就是我们对请求结果的验证结果,也就是一个true or false的过程,上面我们在编写第一个测试用例中的seeJson()和seeJsonStructure()就是Laravel为我们提供的断言函数,用于测试API返回的json是否是预期的结果。
//响应是否成功
$this->assertResponseOk();
//状态码是否是预期的
$this->assertReponseStatus($code)
//判断值是否相等
$this->assertEquals(true);
//...等等等
除此以外,PHPUnti Framework的所有断言均可使用,具体可以查看PHPUnit官方手册Appendix A. Assertions
综上
Laravel phpunit基本的内容也就是这些,当然所有的东西并不会风平浪静的,总会有一些坑,预知坑如何填,点Laravel之PHPUnit问题篇。
开展团队内部测试相关的活动还是很有意义的,比如TDD。我们团队也正在朝着这个方向发展,所以去编写测试吧!
一不小心写了这么久,这么多字,该睡了。