laravel 测试框架

2017-12-16 01:06编辑本页

这里是以 laravel 5.5 为准

其中 phpUnit 的文档在 https://phpunit.de/manual/current/zh_cn/index.html

create

1
2
3
4
5
# 创建测试用例
php artisan make:test XXControllerTest

# 创建单元测试
php artisan make:test XXUnitTest --unit

usage

HTTP

  • json
  • get
  • post
  • put
  • delete

ex:

1
2
3
4
5
6
7
public function testHttpSample()
{
    array $json = [];

    $this->json("PUT", $url, $json)
        ->assertExactJson(['errno' => 0]);
}

可用的 Assertions

Database

数据库部分在官方文档中很详细
主要的assertion就是检查数据库中是否存在某个条目,是否不存在某个条目,以及软删除的检查

1
2
3
4
5
6
7
public function testDbSample()
{
    $this->assertDatabaseHas('sample_table', [
        'id' => '100',
        'data' => 'sample'
    ]);
}

可用的 Assertions

Mocking

官方文档中在这部分只给出了少量的例子,我在实际应用中,有更多有用的用法,如 Log 对象:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public function testLogSample
{
    // 可以用此方法来模拟触发了错误后,
    // 在代码中打印的error log是否和预期一致
    // 以及从此推断出是否触发了预期的错误
    Log::shouldRecive('error')->once()->with('error happened');

    // run test...
    // ...
}

Guzzle

Guzzle 作为发起 HTTP 子请求的重要模块,在 laravel 中的应用也应当被测试用例覆盖到。
Guzzle 提供自己的 Mock 方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public function testGuzzleSample
{
    $mockResponses = [
        [
            200, // code
            ['Content-Type' => 'application/json'], // headers
            '{"errno": 0}' // body
        ]
        [
            500, // code
            ['Content-Type' => 'application/json'], // headers
            '{"errno": 99}' // body
        ]
    ];
    $mockHandler = new Client([
        'handler' => HandlerStack::create(
            (new MockHandler($mockResponses))
        )
    ]);
    $this->app->instance('GuzzleHttp\Client', $mockHandler);

    // run tests...
    // ...
    // 在测试中,guzzle 会按顺序返回定义好的响应,来测试预期的用例。
}

扩展用法:想具体测试子请求中的输入与输出,可以写一个简单MVC类,输入预期子请求的输入(url, method, header, body),来动态生成例子中的 $mockResponses 数组。

env

在 laravel 项目的目录下,有一个 phpunix.xml 文件,在其中可以指定在测试运行时的一些环境变量。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="DB_HOST" value="127.0.0.1"/>
        <env name="DB_PORT" value="3306"/>
        <env name="DB_DATABASE" value="lavaral_test"/>
    </php>
</phpunit>

我在项目中强制指定了测试时使用的数据库地址与名称,为了防止在生产环境中有人运行该脚本,在 .env 文件的设定下,对线上的数据库进行操作。

当然在官方的配置说明中提到,在测试运行时,如果有 .env.testing 的文件存在,在使用 --env=testing 参数限定下,.env.testing 会将 .env 文件覆盖

run

运行测试用例非常简单,只要在项目目录下执行 phpunit 文件即可。

1
./vendor/bin/phpunit

phpunit 还有一些参数可供使用,其中我主要使用的是 --filter,用来执行某个或者某批测试用例。

1
./vendor/bin/phpunit --filter=testHttp

标签: php

点击加载Disqus评论
Creative Commons © 2013 — 2019 xiaocang | Theme based on fzheng.me & NexT | Hosted by Netlify