Research guide
AI E2E Testing Tutorial: Build a Login-to-Checkout Test Without Writing Test Code
The fastest way to understand AI end-to-end testing is not to read another definition. It is to automate a real user journey and deliberately make it fail.
In this tutorial, we will build a browser test that:
- starts from a logged-out state;
- signs in with a controlled test account;
- finds a product or subscription;
- adds it to the cart or selects a plan;
- reaches checkout;
- verifies the order summary before payment;
- stops before performing a real charge.
We will write the scenario in plain English rather than Playwright, Cypress, or Selenium code.
The tutorial uses CueTest as the concrete example because it supports natural-language browser journeys, project environment variables, shared setup hooks, hosted execution, run evidence, visual regression, and CI/API integration. The design principles apply to most modern AI E2E tools.
The important part is not “look how little syntax we typed.” Good E2E testing is about controlling state, defining observable outcomes, keeping the test safe, and making failures useful.
By the end, you will have a test that is small enough to maintain, strict enough to catch a real checkout regression, and flexible enough that a harmless layout change does not require selector surgery.
What we are testing
Assume our demo application has this customer journey:
Sign in
→ browse plans/products
→ choose Standard
→ open cart/checkout
→ verify summary
→ stop before payment
The business requirement is:
A valid customer can sign in, select the Standard product, reach checkout, and see the correct product and price in the final order summary before payment.
Notice what the requirement does not say.
It does not say:
- Billing must be the third sidebar item;
- the button must have CSS class
.primary-button; - the cart must live at
/cart; - checkout must use a modal;
- the product card must be the second
divinside a grid.
Those are implementation details.
Our AI E2E test should be strict about the business contract and flexible about incidental UI structure.
Before you automate: choose a safe environment
Do not begin an AI browser-testing experiment against a production store with a real credit card.
Use one of:
- staging;
- a preview deployment;
- a sandbox tenant;
- a test store;
- a production-safe test account with a non-chargeable payment route.
The agent will interact with the application. Treat it like any automation system with credentials and side effects.
For this tutorial, we assume:
BASE_URL = staging application
TEST_EMAIL = dedicated buyer account
TEST_PASSWORD = test credential
EXPECTED_PRODUCT = Standard
EXPECTED_PRICE = known test-environment price
If your application requires an external payment gateway, stop before final submission unless you have a documented sandbox payment method.
Step 1: create a focused testing project
In CueTest, create a website project for the environment you want to test.
Use a name that makes the scope obvious, for example:
Acme Staging Checkout
Set the project URL to the staging application's base URL.
This project becomes the container for:
- natural-language tests;
- environment variables;
- execution settings;
- run history;
- visual baselines;
- schedules;
- CI settings;
- reports.
Do not mix unrelated applications or environments into one project. When staging and production have different accounts, URLs, data, or visual baselines, separating them makes failures much easier to interpret.
Step 2: store test credentials as environment variables
Do not paste credentials into the test text.
CueTest supports project-level environment variables that can be referenced using syntax such as:
@env:TEST_EMAIL
@env:TEST_PASSWORD
Create values like:
TEST_EMAIL=buyer-e2e@example.test
TEST_PASSWORD=<test password>
EXPECTED_PRODUCT=Standard
EXPECTED_PRICE=$49.00
You can also store environment-specific paths, tenant identifiers, fixture names, or other reusable values.
Why bother for one test?
Because a test suite becomes unmaintainable when credentials and changing values are copied into dozens of scenarios. The test should express meaning; configuration should hold environment-specific data.
Step 3: define the starting state
The easiest way to create a false-positive E2E test is to ignore starting state.
Imagine a previous browser session left:
- the user signed in;
- a product already in the cart;
- a discount applied;
- checkout halfway complete.
Your new test says “add Standard and proceed to checkout.” It passes—but not from a clean user journey.
Before authoring steps, decide the contract:
Starting state:
- user is logged out;
- test buyer account already exists;
- cart is empty;
- no active discount;
- no checkout session is in progress.
How you enforce this depends on your app.
Possible strategies:
- use a fresh isolated browser session;
- run a setup hook that signs out and clears relevant state;
- expose test-only fixture/reset APIs;
- use a dedicated account reset between runs;
- create disposable accounts when appropriate.
Do not ask an AI agent to “figure out a clean state.” Make state management deterministic wherever possible.
Step 4: resist the urge to create one giant prompt
A common first attempt looks like this:
Log in, find Standard, add it to cart, checkout, verify everything works.
It is short and impressive in a demo. It is poor automation.
If the run fails, where did it fail?
What does “everything works” mean?
Was the price checked? Was the right product selected? Did the user actually authenticate, or was an old session reused?
Instead, split the journey into focused steps with explicit expected results.
Step 5: write the login step
Use:
Action:
Open the sign-in page and sign in using @env:TEST_EMAIL and @env:TEST_PASSWORD.
Expected result:
The authenticated customer dashboard is visible and the signed-in account is @env:TEST_EMAIL.
This is better than:
Log in.
because it identifies:
- where to start;
- which account to use;
- what should prove authentication succeeded.
If your product does not show the account email on the dashboard, choose another stable postcondition such as an authenticated navigation item, profile control, or dashboard heading.
What if the login page changes?
Suppose “Sign in” becomes “Log in,” or the form moves from the homepage into an account menu.
An intent-driven system may still find it.
That is acceptable because the requirement is authentication, not the specific position of the login button.
But if the application unexpectedly skips authentication and exposes the dashboard to a logged-out user, the expected account state should fail. Adaptation should not turn a security regression into a passing test.
Step 6: write the product-selection step
Next:
Action:
Find the product or plan named @env:EXPECTED_PRODUCT and select it for purchase.
Expected result:
The selected product is @env:EXPECTED_PRODUCT and the application shows it as the active cart or checkout selection.
This gives the agent freedom to locate the product through the current UI while keeping the selected item explicit.
Avoid instructions like:
Click the second card.
Position is not the business contract.
If there are multiple Standard products, add context:
Select the monthly SaaS subscription named Standard, not any add-on with a similar name.
Natural language works best when ambiguity is removed intentionally.
Step 7: reach checkout without submitting payment
Write:
Action:
Proceed from the selected @env:EXPECTED_PRODUCT to the final checkout review step. Do not submit or authorize payment.
Expected result:
A checkout or order-review screen is visible before payment is submitted.
The safety boundary is important.
“Proceed to checkout” can mean different things across products. Explicitly tell the automation to stop before the destructive or financial action.
For a sandbox payment environment, you may decide to automate full payment later. Start with a non-destructive version first.
Step 8: verify the order summary independently
This is the most valuable step.
Action:
Inspect the checkout summary.
Expected result:
The summary contains @env:EXPECTED_PRODUCT and the displayed product price is @env:EXPECTED_PRICE. The final payment action has not been submitted.
Do not combine “the agent reached checkout” with “therefore checkout is correct.”
The test must verify the business data.
You can expand the postcondition with:
- quantity;
- currency;
- tax;
- discount;
- billing interval;
- user/account identity;
- shipping method;
- total.
But keep the test stable. If tax is intentionally dynamic, do not hard-code a value that changes daily or by environment. Use a fixture or a business rule you can predict.
The complete natural-language test
Our final test now looks conceptually like this:
Test: Customer can reach checkout with the correct Standard product
Starting state:
Use an isolated logged-out browser session. The test buyer exists and the cart is empty.
1. Open the sign-in page and sign in using @env:TEST_EMAIL and @env:TEST_PASSWORD.
Expected: The authenticated customer dashboard is visible and belongs to @env:TEST_EMAIL.
2. Find the product or plan named @env:EXPECTED_PRODUCT and select it for purchase.
Expected: @env:EXPECTED_PRODUCT is the active cart or checkout selection.
3. Proceed to the final checkout review step. Do not submit or authorize payment.
Expected: A checkout/order-review screen is visible before payment submission.
4. Inspect the checkout summary.
Expected: The summary contains @env:EXPECTED_PRODUCT and the displayed product price is @env:EXPECTED_PRICE. Payment has not been submitted.
No CSS selectors.
No page objects.
No manual wait calls.
But importantly, there is still test engineering: state, data, scope, assertions, and safety.
Step 9: run it once and watch the live browser
The first run is not about getting a green check.
Watch what the agent actually does.
Questions to ask:
- Did it enter the intended account?
- Did it choose the correct product?
- Did it take an unexpected shortcut?
- Did it encounter banners or modals?
- Did the expected-result checks match the application state?
- Did it stop before payment?
If the run passes for the wrong reason, fix the test immediately.
For example, suppose the test says:
Expected: checkout page is visible.
and the agent reaches a generic “Cart” page that contains a Checkout button. The expectation is too weak.
Change it to something observable on the actual final review state:
Expected: the final order summary and payment section are visible.
The first run is effectively calibration between product intent and executable intent.
Step 10: inspect the evidence, not only the status
CueTest run reports can include browser evidence such as screenshots, logs, traces, status, usage, and failure analysis.
Use that evidence to answer:
- What did the browser actually show?
- Which step failed?
- What interaction occurred immediately before failure?
- Was the problem in the application, test setup, environment, or AI interpretation?
- Can another engineer reproduce the state?
A green test with no inspectable evidence is weaker than it looks.
A red test with a precise failed step, screenshot, and trace can save substantial debugging time.
Step 11: deliberately change the UI
Now test whether AI adaptation is actually useful.
Make a harmless change in staging:
- move the product list into a new tab;
- rename “Buy now” to “Choose plan”;
- move checkout from a drawer to a full page;
- rearrange cards;
- refactor markup without changing business behavior.
Run the test again.
A good intent-driven system should have a chance to adapt because the expected outcomes remain valid.
If the test requires manual edits for every cosmetic navigation change, it is not reducing much maintenance.
Step 12: deliberately introduce a real regression
This is more important.
Break the product in a way the test must detect.
Examples:
- checkout shows Premium instead of Standard;
- price is incorrect;
- order summary is skipped;
- an unauthenticated user reaches checkout as another user;
- product selection silently chooses the wrong item.
Run the same test.
It should fail.
If the agent works around the regression and still reports success, your test is either underspecified or the platform is adapting too aggressively.
This is the fundamental benchmark for AI E2E testing: adapt to harmless implementation drift; fail on broken business behavior.
Step 13: add visual regression where function is not enough
Our functional test can prove that Standard appears with the correct price.
It cannot necessarily prove that the page looks usable.
The checkout may have:
- overlapping text;
- an invisible white-on-white button;
- a broken product image;
- a collapsed order summary;
- a mobile layout spilling off-screen.
CueTest supports visual regression tests with viewport, full-page, or element captures, baselines, thresholds, masks, and review workflows.
Create a visual check for the final checkout review page if appearance is release-critical.
Stabilize it by:
- using a fixed viewport;
- waiting for the intended state;
- masking timestamps or dynamic IDs;
- using controlled test data;
- reviewing baseline updates rather than auto-approving large diffs.
Functional and visual tests answer different questions.
Step 14: reduce repeated setup with hooks
As your suite grows, multiple tests may require login.
Do not duplicate a long authentication preamble in every scenario if the platform can centralize it.
CueTest projects support lifecycle hooks such as before-run, before-each-test, after-each-test, and after-run behavior.
Use hooks for shared infrastructure-like setup:
Before each test:
Ensure the browser starts logged out and navigate to the project base URL.
or, when a suite intentionally shares authentication:
Before run:
Sign in with the shared test account.
Be careful with shared sessions. They can make tests faster but also create hidden dependencies between scenarios. Use isolated tests when state independence matters.
Step 15: split the suite instead of expanding the mega-flow
Once this test works, the temptation is to add everything:
also apply coupon
also change quantity
also save card
also download invoice
also cancel order
Don't.
Create separate tests:
- customer can sign in;
- customer can add Standard to cart;
- checkout shows correct price;
- valid coupon changes total;
- invalid coupon is rejected;
- customer can complete sandbox payment;
- customer can download invoice after purchase.
Small tests produce better failure isolation and cleaner release decisions.
Step 16: prepare the test for CI
Before putting an AI browser test on every pull request, prove that it is stable manually.
Run it repeatedly against the same build.
Track:
- pass rate;
- runtime;
- AI-assisted recoveries;
- false failures;
- test-data failures;
- average diagnostic time.
Then decide where it belongs.
Good pull-request candidate
A short, stable smoke flow that finishes quickly and gates a high-risk area.
Better post-deploy candidate
A longer adaptive journey that validates the live deployed environment.
Better scheduled candidate
A broad exploratory flow that is valuable but too slow/noisy for every commit.
CueTest supports CI-triggered runs through project CI configuration/API keys. Keep your release-gating suite intentionally small so the output remains actionable.
What the equivalent Playwright test might look like
Natural language is not inherently superior, so compare honestly.
A coded version might be:
import { test, expect } from '@playwright/test';
test('buyer sees correct Standard checkout summary', async ({ page }) => {
await page.goto(process.env.BASE_URL!);
await page.getByRole('link', { name: /sign in/i }).click();
await page.getByLabel(/email/i).fill(process.env.TEST_EMAIL!);
await page.getByLabel(/password/i).fill(process.env.TEST_PASSWORD!);
await page.getByRole('button', { name: /sign in/i }).click();
await expect(page.getByRole('heading', { name: /dashboard/i })).toBeVisible();
const standard = page.getByRole('article').filter({ hasText: 'Standard' });
await standard.getByRole('button', { name: /choose|buy/i }).click();
await page.getByRole('button', { name: /checkout|continue/i }).click();
await expect(page.getByText('Standard')).toBeVisible();
await expect(page.getByText('$49.00')).toBeVisible();
});
That test is perfectly reasonable. Playwright is excellent.
The question is what happens over the next six months.
If the coded version stays stable and your team likes owning it, keep it.
If every billing redesign creates page-object work while the natural-language intent remains unchanged, the AI version may have a lower lifetime cost.
Common mistakes in AI E2E tutorials
Mistake 1: celebrating a one-line prompt
“Test my website” is not a serious test case.
Mistake 2: using uncontrolled production data
Reliable E2E testing needs fixtures and known accounts.
Mistake 3: letting the agent decide success vaguely
Define observable expected results.
Mistake 4: automating destructive actions immediately
Stop before payment/deletion until the safe environment is proven.
Mistake 5: editing prompts until failures disappear
A red run may be a real bug. Diagnose first.
Mistake 6: putting slow agentic tests on every commit
Choose the correct CI stage.
Mistake 7: assuming functional success means visual success
Use visual regression separately when appearance matters.
A reusable template for your next AI E2E test
Copy this structure:
Test name:
[One business behavior]
Starting state:
[Authentication, account/data state, environment]
Test data:
[Environment variables or known fixtures]
Step 1 action:
[User/product intent]
Step 1 expected result:
[Observable state]
Step 2 action:
[User/product intent]
Step 2 expected result:
[Observable state]
Safety constraints:
[Actions the automation must not perform]
Cleanup:
[State that should be removed/reset]
If you cannot fill out the expected-result lines clearly, the requirement probably needs clarification before automation.
Frequently asked questions
Can I really automate E2E tests without writing code?
Yes for many browser journeys. Natural-language and low-code platforms can execute product-level scenarios without the user maintaining a browser framework. Complex custom assertions, test data, integrations, and infrastructure may still require engineering work.
Is an AI E2E test reliable enough for checkout?
It can be, especially when the test stops before real payment, uses controlled data, defines strict postconditions, and retains evidence. Financial or regulated sequences may still benefit from deterministic scripted checks alongside AI coverage.
Should I put login and checkout in one test?
For a tutorial, yes because it demonstrates a complete journey. In a mature suite, keep scenarios focused. You may share login setup while testing checkout behavior separately so failures are easier to diagnose.
What if the agent clicks the wrong product?
The expected result should verify the selected product before continuing. If the platform cannot reliably verify this, the test should fail rather than assume the click was correct.
Should I replace my Playwright checkout test?
Only if the AI version demonstrates lower maintenance or better coverage without reducing trust. Running both for several releases is a better experiment than migrating immediately.
Final takeaway
The useful part of AI E2E testing is not that English is shorter than TypeScript.
It is that you can write the test around a durable business contract:
customer authenticates
→ chooses Standard
→ reaches review
→ sees correct Standard price
→ no payment submitted
while allowing the execution layer to handle some harmless interface change.
That is where AI can remove maintenance without removing rigor.
If you want to try the exact workflow in this tutorial, create one focused website project in CueTest, add controlled environment variables, and start with a safe login-to-review journey. Then change the UI and break the business outcome on purpose. The second run is where you learn whether the automation is actually useful.
Sources and further reading
- CueTest Documentation
- CueTest
- Playwright — Locators
- Playwright — Continuous Integration
- Slack Engineering — Agentic Testing
- Momentic — Agentic Testing
Key takeaways
- The fastest way to understand AI E2E testing is to automate a real user journey and deliberately make it fail.
- Split login-to-checkout into small focused steps with an independent expected result per step instead of one giant prompt.
- Store credentials in environment variables, choose a safe controlled environment, and define the starting state explicitly.
- Verify the order summary independently, never submit real payment, and inspect the retained evidence — not just the pass/fail status.
- Deliberately change the UI and introduce a genuine regression to learn what the suite should catch and what it must not heal.