測試類規則

假設我們有一個簡單的 LoginForm 類,帶有 rules() 方法(在登入頁面中用作框架模板):

class LoginForm {
    public $email;
    public $rememberMe;
    public $password;

    /* rules() method returns an array with what each field has as a requirement.
     * Login form uses email and password to authenticate user.
     */
    public function rules() {
        return [
            // Email and Password are both required
            [['email', 'password'], 'required'],

            // Email must be in email format
            ['email', 'email'],

            // rememberMe must be a boolean value
            ['rememberMe', 'boolean'],

            // Password must match this pattern (must contain only letters and numbers)
            ['password', 'match', 'pattern' => '/^[a-z0-9]+$/i'],
        ];
    }

    /** the validate function checks for correctness of the passed rules */
    public function validate($rule) {
        $success = true;
        list($var, $type) = $rule;
        foreach ((array) $var as $var) {
            switch ($type) {
                case "required":
                    $success = $success && $this->$var != "";
                    break;
                case "email":
                    $success = $success && filter_var($this->$var, FILTER_VALIDATE_EMAIL);
                    break;
                case "boolean":
                    $success = $success && filter_var($this->$var, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null;
                    break;
                case "match":
                    $success = $success && preg_match($rule["pattern"], $this->$var);
                    break;
                default:
                    throw new \InvalidArgumentException("Invalid filter type passed")
            }
        }
        return $success;
    }
}

為了對這個類進行測試,我們使用單元測試(檢查原始碼以檢視它是否符合我們的期望):

class LoginFormTest extends TestCase {
    protected $loginForm;

    // Executing code on the start of the test
    public function setUp() {
        $this->loginForm = new LoginForm;
    }

    // To validate our rules, we should use the validate() method

    /**
     * This method belongs to Unit test class LoginFormTest and
     * it's testing rules that are described above.
     */
    public function testRuleValidation() {
        $rules = $this->loginForm->rules();

        // Initialize to valid and test this
        $this->loginForm->email = "valid@email.com";
        $this->loginForm->password = "password";
        $this->loginForm->rememberMe = true;
        $this->assertTrue($this->loginForm->validate($rules), "Should be valid as nothing is invalid");

        // Test email validation
        // Since we made email to be in email format, it cannot be empty
        $this->loginForm->email = '';
        $this->assertFalse($this->loginForm->validate($rules), "Email should not be valid (empty)");

        // It does not contain "@" in string so it's invalid
        $this->loginForm->email = 'invalid.email.com';
        $this->assertFalse($this->loginForm->validate($rules), "Email should not be valid (invalid format)");

        // Revert email to valid for next test
        $this->loginForm->email = 'valid@email.com';

        // Test password validation
        // Password cannot be empty (since it's required)
        $this->loginForm->password = '';
        $this->assertFalse($this->loginForm->validate($rules), "Password should not be valid (empty)");

        // Revert password to valid for next test
        $this->loginForm->password = 'ThisIsMyPassword';

        // Test rememberMe validation
        $this->loginForm->rememberMe = 999;
        $this->assertFalse($this->loginForm->validate($rules), "RememberMe should not be valid (integer type)");

        // Revert remeberMe to valid for next test
        $this->loginForm->rememberMe = true;
    }
}

Unit 測試究竟如何幫助(不包括一般例子)?例如,當我們得到意想不到的結果時,它非常適合。例如,讓我們從早些時候採取這個規則:

['password', 'match', 'pattern' => '/^[a-z0-9]+$/i'],

相反,如果我們錯過了一件重要的事情並且寫了這個:

['password', 'match', 'pattern' => '/^[a-z0-9]$/i'],

有了幾十種不同的規則(假設我們不只使用電子郵件和密碼),很難發現錯誤。本單元測試:

// Initialize to valid and test this
$this->loginForm->email = "valid@email.com";
$this->loginForm->password = "password";
$this->loginForm->rememberMe = true;
$this->assertTrue($this->loginForm->validate($rules), "Should be valid as nothing is invalid");

將通過我們的第一個例子而不是第二個。為什麼?因為在第二個例子中我們寫了一個帶有拼寫錯誤的模式(錯過了+符號),這意味著它只接受一個字母/數字。

**** 可以使用命令在控制檯中執行單元測試:phpunit [path_to_file]。如果一切正常,我們應該能夠看到所有測試都處於 OK 狀態,否則我們將看到 Error(語法錯誤)或 Fail(該方法中至少有一行未通過)。

使用 --coverage 等附加引數,我們還可以直觀地看到後端程式碼中有多少行被測試以及哪些行已通過/失敗。這適用於已安裝 PHPUnit 的任何框架。

示例 PHPUnit test 在控制檯中的樣子(一般看,不是根據這個例子):

StackOverflow 文件