Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

craig_lovelock's avatar

How to test a multistep checkout journey

Evening, I'm wanting to start adding tests to a new code base but have never gone beyond simple test for API endpoints and the like.

This new project is a checkout journey with multiple pages / steps and finally a payment to Stripe.

Is there any resources on building this sort of test flow?

Each step of this checkout journey allows you to add items to a basket in the database, these items are pulled from a third party (SalesForce) and there's various validation / third party API integrations along the way to check for availability.

My main issue is I can build out the first step, but then for the 2nd page / step I would have to copy and paste the first test as I need the basket to have certain data in it. From here, It would scale up with each test being a copy of the last lot.

0 likes
1 reply
drewdan's avatar

How are you looking to test this? Front end or backend? I think to handle this, you need to work out how you want to test it and what parts you want to test it in.

I don't know of any specific documentation, but some of these pointers might help, and feel free to come back with any tests you have written if you need help to optimise them etc.

If these were PHPUnit tests, I would maybe do some integration tests on the methods. Essentially break the tests down into the bits a method is responsible for. If this method returns a view, test it does that, if this method creates a database entry, test it does that.

You should not have to repeat the tests from a previous step to get to the next stage. The Laravel Factories should allow you to generate the data you require to proceed with a test. For example, if one of the methods was responsible for storing the billing address on an order:

function store(Request $request, Order $order) {
    $data = $request->validate(['whatever validation rules you do');

    $order->billingAddress()->create($data);

    return redirect()->route('checkout.step2');
}

then you might test it like this:

public function testCanStoreBillingAddress() {
    $order = Order::factory()->withDeliveryAddress()->create();

    $this->post('/order/' . $order->id . '/billing_address')->assertStatus(302)->assertSessionDoesNotHaveErrors();

    $this-assertDatabaseHas('billing_address', [// database stuff here]);
}

So in this case, I needed an order, so I just used a factory to generate an order, so I could test with it. (https://laravel.com/docs/8.x/database-testing#defining-model-factories). You can equally do things like add data to the session, set cookies, create other related models. (https://laravel.com/docs/8.x/http-tests#making-requests) - admittedly here, you might have some repetition in the data you need to generate to test, but you could easily abstract this into its own private method on your test, and just call it when you require it.

You might also come across times when you need to send data to an external resource (like Stripe) or get it from an external resource (like Salesforce) - you can use thinks like mocks, to mock the services which get these resources and tell it to return any data you like, this way it makes for more consistent tests and it means less API calls. (https://laravel.com/docs/8.x/mocking)

Please or to participate in this conversation.