來 ! 玩玩PHPUnit的資料庫測試 (上)

發表於2019-03-25

clipboard.png

前言

我一生的文章都會放在這裡,我的部落格,我希望每一行程式碼,每一段文字都能幫助你。https://github.com/CrazyCodes...

大家好,我是CrazyCodes,今天我們來聊聊50%(不完全統計,不必糾結比例 ?)的程式設計師都感覺沒有啥用的資料庫測試。

實際測試是重中之重,正常下來一個需求應當先寫測試用例後實現功能程式碼,如果沒有在開發前做測試,那你可以選擇寫一個錯誤的斷言,使用錯誤斷言來驗證程式碼是否符合預期,而不是根據功能去寫測試,這是寫測試的一種逆向思維。

啥是資料庫測試?

很多人可能玩過單元測試,設定呀,斷言呀,等等條件。但單元測試具有侷限性,現如今大部分程式碼與資料庫耦合度較高,無法獨立進行單元測試,例如要做了登入模組,大概邏輯如下

clipboard.png

那可以用單元測試的地方有哪些呢?

  1. 對使用者名稱新增正規表示式(或者是規則)進行單元測試
  2. 對使用者密碼新增正規表示式(或者是規則)進行單元測試

但是否發現驗證使用者是否存在就無法使用單元測試進行預期的判斷了?這時候就需要做資料庫測試了,資料庫測試實際很簡單,大概的流程如下

clipboard.png

我們不看官方文件的例子,因為那對新人來說很多名詞難於理解,如果你準備好了,那接下來,讓我們通過實操來初試資料庫測試吧!

準備測試資料

在準備資料前,來看看PHPUnit為我們準備的幾種測試資料檔案的格式。

Flat XML DataSet (平直 XML 資料集)

<?xml version="1.0" ?>
<dataset>
    <user id="1" username="zhangsan" password="12345" created="2019-03-25 17:15:23" />
    <user id="2" username="lisi" password="12345" created="2019-03-25 12:14:20" />
</dataset>

就是如上這樣,上述的結構大概意思如下

  • user 表名
  • username user表內的username欄位
  • password user表內的pssword欄位
  • created user表內的created欄位

每一個以 /> 結束為一條測試資料

XML DataSet (XML 資料集)

<?xml version="1.0" ?>
<dataset>
    <table name="user">
        <column>id</column>
        <column>username</column>
        <column>password</column>
        <column>created</column>
        <row>
            <value>1</value>
            <value>zhangsan</value>
            <value>123456</value>
            <value>2019-03-25 17:15:23</value>
        </row>
        <row>
            <value>2</value>
            <value>lisi</value>
            <value>123456</value>
            <value>2019-03-25 17:15:23</value>
        </row>
    </table>
</dataset>

上述XML與第一個XML表達形式不同,但大概是一個意思

  • 首先宣告瞭使用哪張表 <table name="user">
  • 每行資料的包裹標籤為 <row>
  • <value> 標籤一一對應標籤 <column>

就跟SQL語句

UPDATE table_name SET field1=new-value1, field2=new-value2

一樣。什麼?你需要創造的測試資料太多?一個一個填會不會累死?那下面就是你的福音了

MySQL XML DataSet (MySQL XML 資料集)

Unit 可直接使用MySQL匯出的資料集,你可以在MySQL控制檯使用命令

mysqldump --xml -t -u [username] --password=[password] [database] > /path/to/file.xml

這是直接匯出指定庫的所有表資料,如果想指定庫你可以這樣做

mysqldump --xml -t -u [username] --password=[password] [database] [table1] [table2] > /path/to/file.xml

匯出的資料大概如下

<?xml version="1.0"?>
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <database name="testdatabase">
        <table_data name="user">
               <field name="id">1</field>
               <field name="username">zhangsan</field>
               <field name="password">123456</field>
               <field name="created">2019-03-25 17:15:23</field>
        </table_data>
    </database>
</mysqldump>

YAML DataSet (YAML 資料集)

user:
  -
    id: 1
    username: "zhangsan"
    password: "123456"
    created: 2019-03-25 17:15:23
  -
    id: 2
    username: "lisi"
    password:"123456"
    created: 2019-03-25 17:15:23

相信看到這裡,我不用解釋你也能看懂了。

其他

更多的檔案格式請參照 https://phpunit.readthedocs.i...
並不是你喜好哪個格式就用哪個,要根據業務來,通過上面的幾種方式,我們可以看出,類似於動態的資料,例如欄位 created 我們不需要他是一個固定的值,而是根據時間變化,這種情況你只能讓

世界上最好的語言 PHP

來幫你了。

<?php
use PHPUnit\Framework\TestCase;
use PHPUnit\DbUnit\TestCaseTrait;

class IsUserTest extends TestCase
{
    use TestCaseTrait;

    protected function getDataSet()
    {
        return new UserTest(
            [
                'user' => [
                    [
                        'id' => 1,
                        'username' => 'zhangsan',
                        'password' => '123456',
                        'created' => '2019-03-25 17:15:23'
                    ],
                    [
                        'id' => 2,
                        'username' => 'lisi',
                        'password' => '123456',
                        'created' => '2019-03-25 17:15:23'
                    ],
                ],
            ]
        );
    }
}
?>

當然你需要實現一個自定義的資料庫測試類,官方提供的這個已經夠用了,你也可以隨意更改以達到你的測試目的

<?php
class UserTest extends PHPUnit_Extensions_Database_DataSet_AbstractDataSet
{
    /**
     * @var array
     */
    protected $tables = [];

    /**
     * @param array $data
     */
    public function __construct(array $data)
    {
        foreach ($data AS $tableName => $rows) {
            $columns = [];
            if (isset($rows[0])) {
                $columns = array_keys($rows[0]);
            }

            $metaData = new PHPUnit_Extensions_Database_DataSet_DefaultTableMetaData($tableName, $columns);
            $table = new PHPUnit_Extensions_Database_DataSet_DefaultTable($metaData);

            foreach ($rows AS $row) {
                $table->addRow($row);
            }
            $this->tables[$tableName] = $table;
        }
    }

    protected function createIterator($reverse = false)
    {
        return new PHPUnit_Extensions_Database_DataSet_DefaultTableIterator($this->tables, $reverse);
    }

    public function getTable($tableName)
    {
        if (!isset($this->tables[$tableName])) {
            throw new InvalidArgumentException("$tableName is not a table in the current database.");
        }

        return $this->tables[$tableName];
    }
}
?>

準備驗證資料

驗證資料與測試資料格式一樣。都是官方文件的那幾種。例如你希望插入資料庫後的結果是

<?xml version="1.0" ?>
<dataset>
    <user id="1" username="zhangsan" password="12345" created="2019-03-25 17:15:23" />
    <user id="2" username="lisi" password="12345" created="2019-03-25 12:14:20" />
</dataset>

那在執行測試時,unit則會將該xml檔案對比資料庫中的資料。一樣則通過測試。就是這麼簡單。

致謝

充分掌握上述的格式以及官方文件內的demo,概念等,才能將資料庫掌握在自己手中。下一章我會根據上述準備的資料準備一次“實戰演習”,我已經幫你開了頭,剩下的就看你自己的了。

感謝你看到這裡,希望本篇文章可以幫到你。

相關文章