珍爱生命,拥抱 PHPUnit

在公司负责服务端 Api 开发,为安卓客户端提供相应的接口,在开发的过程中,免不了要测试完成的接口是否可用。最开始的测试手段是使用 POSTMAN 等工具发送请求。使用这类工具的流程一般是,先构造 url 请求接口进行登录,登录后拿到服务器返回的一个标识(可以看做是一个 session,但这个 session 的概念和传统的网站开发中的 session 概念不一样),在后续的接口调用中,都需要在请求 header 头里面加上那个标识。这个流程会比较繁琐,至少需要多次鼠标点击以及复制粘贴的过程才能完成。偶尔这样做还好,这种事情做多了便让我觉得烦躁无比。

了解了下 PHPUnit,先读了读官网的 manual,大体明白怎么写测试了就开始动手。

具体到我们的业务,首先写了一个 Client 类,这个类主要作用是模仿客户端发一个请求,当然这个类会进行一些简单的封装,比如 curl 请求的时候带上我们的标识(上文说的 session),还有其它的模拟安卓客户端的一些请求头。刚开始我在每个测试方法中都 new 一个 Client 对象,后来想想不对,既然是模仿客户端,而一个客户端永远是一个实例,每次 new 一个出来显然不符合现实逻辑,另外一个问题是,测试登录接口后,session 标识需要在后续的接口测试中反复使用。想到这,于是将 Client 类改为了单例实现,这样就能保证在多个测试方法的 Client 为同一个实例对象,并能共享 session 标识状态。

下面是 Client 的实现及一个简单的测试用例文件示例:

class Client
{
    private function __construct()
    {
    }

    private static $instance;

    public $session;

    public function getInstance()
    {
        if (is_null(static::$instance)) {
            static::$instance = new static();
        }
        return static::$instance;
    }

    public function curl($url)
    {
        $ch = curl_init();
        if (!is_null($this->session)) {
            // 如果 session 不为空,则在 curl 请求时加上保存 session 信息的 header 头
        }
        // 使用 curl 发送请求
        $response = curl_exec($ch);
        return $response;
    }
}

class Test extends PHPUnit_Framework_TestCase
{
    public function testLogin()
    {
        $client = Client::getInstance();
        $response = $client->curl($login_url);
        // 下面就可以进行一些 assert 啦

        // 登录成功后设置 session 为服务器返回的 session
        $client->session = $session_get_from_response;
    }

    /**
     * @depends testLogin
     */
    public function testGetUserInfo()
    {
        $client = Client::getInstance();
        $response = $client->curl($get_user_info_url);
        // 接下来的代码进行后续处理
    }
}

要测试新的接口,只需要增加新的方法就好了,多次测试多次运行单元测试命令就 OK 了,可以节约大量时间啊。

另外,我发现在单元测试类里面的不同方法好像是单独运行的,比如下面的这个代码:

class Test2 extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        $GLOBALS['count'] += 1;
        echo $GLOBALS['count'];
    }

    public function testTwo()
    {
        $GLOBALS['count'] += 2;
        echo $GLOBALS['count'];
    }
}

输出结果为 1 2 ,并不是想象中的 1 3,这是为什么呢?