PHP Test des règles de classe


Exemple

Disons que nous avons une classe LoginForm simple avec la méthode rules () (utilisée dans la page de connexion comme modèle d' LoginForm ):

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;
    }
}

Pour effectuer des tests sur cette classe, nous utilisons les tests unitaires (vérification du code source pour voir si cela correspond à nos attentes):

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;
    }
}

Comment exactement les tests Unit peuvent-ils aider (en excluant les exemples généraux) ici? Par exemple, cela convient très bien lorsque nous obtenons des résultats inattendus. Par exemple, prenons cette règle plus tôt:

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

Au lieu de cela, si nous avons raté une chose importante et écrit ceci:

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

Avec des douzaines de règles différentes (en supposant que nous utilisons non seulement le courrier électronique et le mot de passe), il est difficile de détecter les erreurs. Ce test unitaire:

// 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");

Va passer notre premier exemple mais pas le second . Pourquoi? Parce que dans le deuxième exemple, nous avons écrit un motif avec une faute de frappe (signe + raté), ce qui signifie qu’il n’accepte qu’une lettre / un chiffre.

Les tests unitaires peuvent être exécutés dans la console avec la commande: phpunit [path_to_file] . Si tout va bien, nous devrions être en mesure de voir que tous les tests sont en OK état, sinon nous verrons soit Error (erreurs de syntaxe) ou Fail (au moins une ligne de cette méthode n’est pas passée).

Avec des paramètres supplémentaires tels que --coverage nous pouvons également voir visuellement combien de lignes du code backend ont été testées et celles qui ont réussi / échoué. Cela s'applique à tout framework ayant installé PHPUnit .

Exemple de l'apparence du test PHPUnit dans la console (aspect général, pas selon cet exemple):

entrer la description de l'image ici