ella-stinnes's avatar

What should I test?

I'm new to testing so I'm trying to figure out what I should test.

I have a CRUD for managing company details.

The application has 8 different user roles, some users can access the full CRUD, some are read only and others cannot see the company details at all.

Should I be creating 8 tests for the different user roles?

Once I've tested the authorisation, I'm guessing I should have form validation tests - if there's 10 fields on the page, do I create 10 validation tests? Or one test to cover all 10 fields?

Then there's the store/update methods, I'm guessing I assert the database contains the values.

Do you have a testing workflow for a standard CRUD as to what should be covered?

I'm not sure if I'm writing too many tests.

0 likes
5 replies
ella-stinnes's avatar

Thank you both, I'll look at the Pest Driven Laravel series although this appears to be TDD?

Does this cover a general rule of thumb as to what should be tested?

JussiMannisto's avatar

I haven't watched that video series. I'm just sharing my preferences.

I test business-critical features, such as authentication, authorization, and the basic flow of the app. If a user can order something, for example, then I'll definitely test that process from start to finish, with all variants, and any error states that could occur.

In other words, I test the things that absolutely positively must not break.

Unit tests are a bit different. If a component is complicated or frequently modified, it's a good idea to write tests for it. However, I wouldn't worry about testing every single little thing just to get a higher test coverage %.

martinbean's avatar
Level 80

@ella-stinnes Sounds like data providers and/or the “test with” utility would be a good solution for your use cases. They basically let you re-run a single test case multiple times, but with a different input each time.

The application has 8 different user roles, some users can access the full CRUD, some are read only and others cannot see the company details at all.

Should I be creating 8 tests for the different user roles?

Using a data provider, you’d have a single test case (e.g. test_create_company), that could take a user role and the expected result as inputs:

#[TestWith(['admin', true])]
#[TestWith(['moderator', true])]
#[TestWith(['member', false])]
// And your other roles...
public function test_create_company(string $role, bool $expected): void
{
    $user = User::factory()->role($role)->createOne();

    $this->assertDatabaseEmpty('companies');

    $response = $this->actingAs($user)->post('/companies', [
        // Valid company data...
    ]);

    if ($expected) {
        $response->assertRedirect()->assertValid();

        $this->assertDatabaseHas('companies', [
            // Fields and values that should exist in database...
        ]);
    } else {
        $response->assertForbidden();

        $this->assertDatabaseEmpty('companies');
    }
}

So the above test case will create a user with the given role and attempt to create a company. Then, depending on the expected result, will either assert the request was successful and a record was inserted into the database, or assert a 403 Forbidden response was returned and no company records were created.

Once I've tested the authorisation, I'm guessing I should have form validation tests - if there's 10 fields on the page, do I create 10 validation tests? Or one test to cover all 10 fields?

Again, you can use a data provider for say, testing required fields. For most resources in my applications, I‘ll have a test method that looks like this:

#[TestWith(['name'])]
#[TestWith(['description'])]
#[TestWith(['email'])]
#[TestWith(['telephone_number'])]
#[TestWith(['website_url'])]
public function test_field_is_required(string $field): void
{
    $user = User::factory()->role('admin')->createOne();

    $data = [
        'name' => fake()->company(),
        'email' => fake()->safeEmail(),
        // All other fields with a valid value...
    ];

    Arr::forget($data, $field);

    $this
        ->actingAs($user)
        ->post('/companies', $data)
        ->assertInvalid($field);
}

The above test case will then be re-ran multiple times with a different field name provided as an argument each time. The test case has an array of “valid” data, but then removes the named field, and asserts the request throws a validation error for that named field.

1 like

Please or to participate in this conversation.