Laravel, PHP, Programming, Testing

How To Write Tests For a Custom Laravel Validation Rule

Scenario

Our form is expecting user input from a specific field is typed in all capital letters so we have a custom validation rule to check if the input is uppercase. Writing tests for a custom Laravel validation rule is simple once you get started.

Example Custom Rule

The uppercase rule is the example from the Laravel docs. Here’s what the class looks like.

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

Writing Tests

When we’re writing tests we need to think of the use cases or scenarios that may occur. In our case we have a few different types of strings that should be invalid and only one case when it will be valid.

Take the word flowers for example. The only valid way to pass our new rule would be FLOWERS. These are the different scenarios or tests cases we may want to test so that we know our validation rule validates every type of use case.

- FLOWERS // Valid

- Flowers // Invalid
- flowers // Invalid

Now we know which use cases should pas and faile lets write the tests. Our test class would look something like this.

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    public function testAllUppercasePasses()
    {
        $rule = new App\Rule\Uppercase()
        $this->assertTrue($rule->passes('attribute', 'FLOWERS');
    }

    public function testOneUppercaseLetterIsInvalid()
    {
        $rule = new App\Rule\Uppercase()
        $this->assertTrue($rule->passes('attribute', 'Flowers');
    }

    public function testAllLowercaseIsInvalid()
    {
        $rule = new App\Rule\Uppercase()
        $this->assertTrue($rule->passes('attribute', 'flowers');
    }
}

Each test is asserting a different use case. Separate tests are easier to read and when something fails it’s easier to determine what failed.

Now that we have tests for our rule we know when using this rule as a part of validation that it will work. If for some reason it doesn’t work write a test for the scenario it didn’t work for. Watch the test fail. Fix the scenario and watch the test pass. Rinse and repeat.

Happy testing!

Share this Story
Load More Related Articles
Load More By Nick Escobedo
Load More In Laravel

Check Also

Understanding Trade-offs as a Developer

Trade-offs are one of the most important aspects ...