iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
Software Development

開心撰寫 PHPUnit系列 第 13

Day13. 重構爬蟲測試 - Mockery spy

  • 分享至 

  • xImage
  •  

Yes

在上一篇我們的測試程式如下

<?php

namespace Recca0120\Ithome30\Tests;

use Mockery;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\TestCase;
use Recca0120\Ithome30\PttCrawler;
use Psr\Http\Client\ClientInterface;

class PttCrawlerTest extends TestCase
{
    public function test_fetch_board_page()
    {
        /** @var Mockery\Mock|ClientInterface $httpClient */
        $httpClient = Mockery::mock(ClientInterface::class);
        $httpClient
            ->allows('sendRequest')
            ->andReturn(new Response(200, [], file_get_contents(__DIR__ . '/fixtures/ptt_home.html')));

        $crawler = new PttCrawler($httpClient);
        $records = $crawler->all();

        self::assertEquals([
            'name' => 'Gossiping',
            "nuser" => '12185',
            'class' => '綜合',
            'title' => '[八卦]不停重複今日公祭明日忘記',
        ], $records[0]);
    }
}

這樣的測試程式其實是不夠好的,因為我們從測試程式碼只看得出

  • 需要使用 HttpClient 去抓取資料
  • 分析網頁並回傳結果

但還有一個也很重要的資訊網址我們並沒有驗證到啊。但網址又在 PttCrawler 裡,那該怎麼驗證這段程式碼呢?這時我們就可以使用 Mockery::spy 來進行驗證(顧名思意就是放個間諜到程式裡囉),所以我們的測試程式就可以改為

<?php

namespace Recca0120\Ithome30\Tests;

use Mockery;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\TestCase;
use Recca0120\Ithome30\PttCrawler;
use Psr\Http\Client\ClientInterface;

class PttCrawlerTest extends TestCase
{
    public function test_fetch_board_page()
    {
        /** @var Mockery\Mock|ClientInterface $httpClient */
        // mock 改為 spy
        $httpClient = Mockery::spy(ClientInterface::class);
        $httpClient
            ->allows('sendRequest')
            ->andReturn(new Response(200, [], file_get_contents(__DIR__ . '/fixtures/ptt_home.html')));

        $crawler = new PttCrawler($httpClient);
        $records = $crawler->all();

        self::assertEquals([
            'name' => 'Gossiping',
            "nuser" => '12185',
            'class' => '綜合',
            'title' => '[八卦]不停重複今日公祭明日忘記',
        ], $records[0]);

        // 新增驗證
        $httpClient->shouldHaveReceived('sendRequest')->once()->with(Mockery::on(function (Request $request) {
            return (((string)$request->getUri()) === 'https://www.ptt.cc/bbs/hotboards.html');
        }));
    }
}

調整完後我們就可以從測試很清楚的看出這隻程式的目的為

  • 使用 HttpClient 抓取 https://www.ptt.cc/bbs/hotboards.html 的網頁資料
  • 分析網頁並回傳結果

只看測試案例的時候就能大致理解整個程式的輪廓是相當重要的,因為這樣的測試程式幾乎就已經等同於說明書了,並且我們在測試程式裡保留了『完整的原始資訊』,不論任何時候需要重構程式或改寫程式,我們都不必擔心最後寫出的結果會不一致了


上一篇
Day 12. 重構爬蟲 - 移除不必要的 Interface
下一篇
Day14. 重構爬蟲測試 - 爬蟲的利器 PHPVCR
系列文
開心撰寫 PHPUnit30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言