PHP 测试课程规则

示例

假设我们有一个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', 'password'], 'required'],

            // 电子邮件必须为电子邮件格式
            ['email', 'email'],

            // RememberMe必须为布尔值
            ['rememberMe', 'boolean'],

            // 密码必须与此模式匹配(必须仅包含字母和数字)
            ['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;

    // 在测试开始时执行代码
    public function setUp() {
        $this->loginForm = new LoginForm;
    }

    // 为了验证我们的规则,我们应该使用validate()方法

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

        // 初始化以验证并对此进行测试
        $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");

        // 测试电子邮件验证
        // 由于我们将电子邮件设置为电子邮件格式,因此不能为空
        $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)");

        // 将电子邮件恢复为下一次测试有效
        $this->loginForm->email = 'valid@email.com';

        // 测试密码验证
        // 密码不能为空(因为这是必需的)
        $this->loginForm->password = '';
        $this->assertFalse($this->loginForm->validate($rules), "Password should not be valid (empty)");

        // 将密码恢复为下一次测试有效
        $this->loginForm->password = 'ThisIsMyPassword';

        // 测试记住我的验证
        $this->loginForm->rememberMe = 999;
        $this->assertFalse($this->loginForm->validate($rules), "RememberMe should not be valid (integer type)");

        // 将retberMe恢复为下一次测试有效
        $this->loginForm->rememberMe = true;
    }
}

Unit在这里,测试究竟能为您提供什么帮助(不包括一般示例)?例如,当我们获得意外结果时,它非常适合。例如,让我们从前面的规则开始:

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

相反,如果我们错过了一件重要的事情,并写了这样的话:

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

由于存在许多不同的规则(假设我们不仅使用电子邮件和密码),还很难发现错误。本单元测试:

// 初始化以验证并对此进行测试
$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测试在控制台中的外观(总体外观,而不是根据此示例):