天天看點

利用PHP記憶體資料庫進行全面的單元測試

作者:不秃頭程式員
利用PHP記憶體資料庫進行全面的單元測試

介紹

單元測試是軟體開發中的一個基本實踐,確定代碼的各個元件在隔離的情況下正确運作。有效地管理測試資料是單元測試的一個關鍵方面,而PHP記憶體資料庫在實作這一目标方面可以發揮關鍵作用。在這篇部落格中,我們将探索用例,并提供代碼示例,用于實作PHP記憶體資料庫進行單元測試。

什麼是PHP記憶體資料庫?

用于單元測試的PHP記憶體資料庫是完全在記憶體(RAM)中運作的資料庫系統。它專門設計用于在單元測試期間促進測試資料的建立和管理。與傳統資料庫不同,用于測試的記憶體資料庫不需要安裝或拆卸腳本,使測試安裝和清理更有效。

記憶體資料庫的用例

  • 隔離:記憶體資料庫允許您将測試彼此完全隔離。每個測試都可以使用幹淨的石闆,消除測試之間的幹擾。
  • 速度:記憶體中的操作明顯快于基于磁盤的資料庫操作,進而減少了執行測試所需的時間。
  • 資料一緻性:使用記憶體資料庫,您可以通過為每個測試設定特定的狀态來確定資料的一緻性,進而保證您的測試産生可預測的結果。
  • 資源效率:記憶體資料庫是輕量級的,不需要外部伺服器程序或磁盤存儲,這使得它們在運作測試時具有資源效率。
  • 消除依賴性:您可以消除對外部資料庫、API或服務的依賴性,使您的測試更加獨立和可移植。

為單元測試實作PHP記憶體資料庫

在我們的示例中,我們将使用SQLite作為記憶體資料庫,這是在PHP中建立輕量級記憶體資料庫的流行選擇。

設定

首先,設定SQLite記憶體資料庫并建立一個表進行測試。下面是一個示例設定代碼:

class MemoryDatabaseTest extends PHPUnit\Framework\TestCase
{
    protected $pdo;

    public function setUp(): void
    {
        $this->pdo = new PDO('sqlite::memory:');
        $this->pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT)');
    }
    // ... Rest of your setup logic
}           

測試資料處理

您現在可以編寫與記憶體資料庫互動的測試,例如插入、更新或查詢資料:

public function testInsertData()
{
    $stmt = $this->pdo->prepare('INSERT INTO users (username) VALUES (:username)');
    $stmt->execute([':username' => 'JohnDoe']);
    $this->assertEquals(1, $stmt->rowCount());
}
public function testQueryData()
{
    $stmt = $this->pdo->query('SELECT * FROM users');
    $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $this->assertEquals('JohnDoe', $users[0]['username']);
}
// ... Additional data manipulation tests           

清理

每次測試後不要忘記清理,以確定下一次測試的新鮮環境:

public function tearDown(): void
{
    $this->pdo = null; // Close the database connection
}           

處理異常

您可以編寫測試用例來覆寫抛出異常的場景,例如嘗試插入重複資料:

public function testInsertDuplicateData()
{
    $this->expectException(PDOException::class);
    // Insert data
    $stmt = $this->pdo->prepare('INSERT INTO users (username) VALUES (:username)');
    $stmt->execute([':username' => 'JohnDoe']);
    // Attempt to insert duplicate data
    $stmt->execute([':username' => 'JohnDoe']);
}
// ... Other exception handling tests           

測試資料庫架構

您還可以編寫測試來確定資料庫模式的正确性:

public function testTableSchema()
{
    $stmt = $this->pdo->query('PRAGMA table_info(users)');
    $columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $this->assertCount(2, $columns); // Expecting two columns (id and username)
    $this->assertEquals('id', $columns[0]['name']);
    $this->assertEquals('username', $columns[1]['name']);
}
// ... Other schema-related tests           

使用資料提供程式

對于更複雜的方案或具有預定義的資料集時,可以在運作測試之前使用資料提供程式用測試資料填充資料庫。在這個例子中,我們将測試插入多個使用者:

/**
 * @dataProvider userProvider
 */
public function testInsertMultipleUsers($username)
{
    $stmt = $this->pdo->prepare('INSERT INTO users (username) VALUES (:username)');
    $stmt->execute([':username' => $username]);
    $stmt = $this->pdo->query('SELECT * FROM users WHERE username = :username');
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    $this->assertEquals($username, $user['username']);
}
public function userProvider()
{
    return [
        ['Alice'],
        ['Bob'],
        ['Charlie'],
    ];
}
// ... Other tests using data providers           

測試交易

可以通過在測試中開始、復原或送出事務來測試資料庫事務。此示例測試復原行為:

public function testTransactionRollback()
{
    // Begin a transaction
    $this->pdo->beginTransaction();

    // Insert data
    $stmt = $this->pdo->prepare('INSERT INTO users (username) VALUES (:username)');
    $stmt->execute([':username' => 'JohnDoe']);
    // Rollback the transaction
    $this->pdo->rollBack();
    // Verify that the data was not inserted
    $stmt = $this->pdo->query('SELECT * FROM users WHERE username = "JohnDoe"');
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    $this->assertFalse($user); // Expecting false as the user should not exist
}
// ... Other transaction-related tests           

處理異常

測試用例還可以覆寫抛出異常的場景。下面是一個測試示例,確定在嘗試插入重複資料時抛出異常:

public function testInsertDuplicateData()
{
    $this->expectException(PDOException::class);
    // Insert data
    $stmt = $this->pdo->prepare('INSERT INTO users (username) VALUES (:username)');
    $stmt->execute([':username' => 'JohnDoe']);
    // Attempt to insert duplicate data
    $stmt->execute([':username' => 'JohnDoe']);
}           

測試資料庫架構

您還可以編寫測試來確定資料庫模式的正确性:

public function testTableSchema()
{
    $stmt = $this->pdo->query('PRAGMA table_info(users)');
    $columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $this->assertCount(2, $columns); // Expecting two columns (id and username)
    $this->assertEquals('id', $columns[0]['name']);
    $this->assertEquals('username', $columns[1]['name']);
}           

使用資料提

資料提供程式可用于使用不同的輸入資料運作相同的測試。在這個例子中,我們将測試插入多個使用者:

/**
 * @dataProvider userProvider
 */
public function testInsertMultipleUsers($username)
{
    $stmt = $this->pdo->prepare('INSERT INTO users (username) VALUES (:username)');
    $stmt->execute([':username' => $username]);
    $stmt = $this->pdo->query('SELECT * FROM users WHERE username = :username');
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    $this->assertEquals($username, $user['username']);
}
public function userProvider()
{
    return [
        ['Alice'],
        ['Bob'],
        ['Charlie'],
    ];
}           

測試交易

還可以通過在測試中開始、復原或送出事務來測試資料庫事務。此示例測試復原行為:

public function testTransactionRollback()
{
    // Begin a transaction
    $this->pdo->beginTransaction();
  // Insert data
    $stmt = $this->pdo->prepare('INSERT INTO users (username) VALUES (:username)');
    $stmt->execute([':username' => 'JohnDoe']);
    // Rollback the transaction
    $this->pdo->rollBack();
    // Verify that the data was not inserted
    $stmt = $this->pdo->query('SELECT * FROM users WHERE username = "JohnDoe"');
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    $this->assertFalse($user); // Expecting false as the user should not exist
}           

結論

PHP記憶體資料庫,如SQLite記憶體資料庫,為單元測試提供了一種高效可靠的測試資料管理方法。通過遵循本部落格中概述的原則,并将這些實踐融入到單元測試工作流程中,您可以確定單元測試快速,隔離和自包含,最終導緻更健壯和可靠的PHP代碼。測試愉快!

繼續閱讀