ScreenshotNeo

BlogHow-to

How to Write Your First Test Automation Script

Write and run a first Selenium test in Python: open a page, submit a form, assert the result, and close the browser safely.

By the ScreenshotNeo team4 October 20268 min read

A useful first browser automation script does five things: opens a known page, locates a control, performs an action, asserts the visible result, and closes the browser. This guide uses Selenium with Python to submit Selenium’s example web form and verify its response. The assertion is what turns browser activity into a test.

1. Decide what the test proves

Keep the first check narrow and observable. Here, the behavior is: entering “Hello Selenium!” in the form and submitting it should display “Received!” on the result page. If the page does not show that message, the test fails.

This avoids a common beginner mistake: automating clicks without checking an outcome. A script that clicks Submit but never checks the response cannot tell you whether the behavior worked.

2. Choose a framework and install its prerequisites

This example uses Selenium because its WebDriver API is available in several languages and its official first-script guide follows the same basic flow. Selenium setup includes a language binding, a browser, and the browser’s WebDriver implementation. Selenium Manager can help manage drivers in current Selenium releases, but browser and environment setup still varies; follow the current official installation guidance for your OS and browser. See Selenium’s getting-started guide and language library installation instructions.

  1. Install a supported Python version and make a project directory.
  2. Create and activate a virtual environment: python -m venv .venv; on macOS/Linux run source .venv/bin/activate, and on Windows PowerShell run .venv\Scripts\Activate.ps1.
  3. Install Selenium: python -m pip install selenium.
  4. Install a compatible browser such as Chrome or Firefox. Consult Selenium’s current browser and driver guidance if automatic driver management cannot find a usable driver.

Use the Python executable from the activated environment for both installation and execution. If your project already uses another language, Selenium has bindings for multiple languages; use that language’s official setup page instead of translating commands by guesswork. Playwright is another option with its own setup and APIs. Its official test-writing guide shows actions and assertions with automatic waiting behavior. Choose based on your project’s language, browser requirements, team conventions, and existing test runner; neither framework is a universal fit.

3. Write and run the first script

Create first_test.py. This standalone version uses an explicit wait for the result and a finally block so the browser session is closed even if navigation, locating, or the assertion fails.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


def main():
    driver = webdriver.Chrome()
    try:
        driver.get("https://www.selenium.dev/selenium/web/web-form.html")

        text_box = driver.find_element(By.NAME, "my-text")
        submit_button = driver.find_element(By.CSS_SELECTOR, "button")

        text_box.send_keys("Hello Selenium!")
        submit_button.click()

        message = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located((By.ID, "message"))
        )
        assert message.text == "Received!", (
            f"Expected 'Received!', got {message.text!r}"
        )
        print("PASS: the form displayed the expected response")
    finally:
        driver.quit()


if __name__ == "__main__":
    main()

Run it from the project directory with python first_test.py (or python3 first_test.py where that is your Python command). Selenium’s official example uses this same public form and demonstrates the driver, navigation, locators, interaction, response, and quit sequence: Write your first Selenium script.

What each part does

  • webdriver.Chrome() starts a browser session. Selenium communicates with the browser through WebDriver.
  • driver.get(...) navigates to the test page.
  • find_element locates elements by a meaningful attribute or CSS selector. The form field has the name my-text; the response has the ID message.
  • send_keys enters text and click submits the form.
  • WebDriverWait waits up to ten seconds for the response to become visible. It checks repeatedly, so a fast response proceeds quickly without a fixed long sleep.
  • assert compares the actual response with the expected one. A mismatch raises an error and makes the script exit unsuccessfully.
  • finally runs cleanup on both success and failure. quit() ends the session and closes its browser windows.

4. Make the test fit your own page

Replace the sample URL, locators, action, and expected result with those for your application. First identify the user-visible behavior you want to protect, then write the assertion in plain language before coding it.

Locators

Prefer stable identifiers that describe the intended control. Selenium supports strategies including ID, name, CSS selector, and XPath. IDs, names, and application-provided test attributes are often clearer than selectors tied to layout. For example, By.ID, "submit-order" is easier to understand than a long chain of nested CSS classes. Avoid selecting an element only because it is currently the third button on the page.

Use find_element when one matching element is expected; it raises an exception if none is found. Use find_elements when zero or more matches are valid; it returns a list, which you can assert is non-empty or check for a particular item. Scope a search to a parent element when several controls share similar labels.

Waits and asynchronous pages

Modern pages often render or update after the initial navigation. Wait for the condition that matters, such as an element becoming visible or a result text changing. Keep the timeout bounded and make it long enough for the environment under test. Avoid adding a large fixed sleep just to hide timing problems: it slows every run and can still be too short on a slower run.

Selenium supports implicit waits as well as explicit waits. Avoid mixing implicit and explicit waits casually because their combined timing can be hard to reason about. This sample uses an explicit wait for the specific result and does not set an implicit wait.

Assertions and failure meaning

Write assertions that describe the product behavior: expected text, URL, enabled state, or another observable result. Include useful expected and actual values in failure messages. If the test passes without checking a result, it proves only that the commands ran without raising an error.

5. Common errors and fixes

Symptom Likely cause Fix
ModuleNotFoundError: No module named 'selenium' Selenium was installed into a different Python environment. Activate the project virtual environment, then run python -m pip install selenium and execute the script with that same Python.
Driver or browser startup error The browser is absent, unsupported, or a driver cannot be found or started. Install/update the browser and Selenium binding, check the current Selenium driver setup guidance, and verify the browser can launch in your user account. In containers, ensure the image includes required browser dependencies.
NoSuchElementException The locator is wrong, the page differs, or the element is not present yet. Inspect the current page and confirm the exact ID/name/selector. If rendering is asynchronous, wait for the element with an explicit condition rather than immediately searching.
TimeoutException The expected condition did not become true before the wait expired. Check whether navigation succeeded, whether a validation error appeared, and whether the locator and expected condition match the page. Increase the timeout only if the behavior legitimately takes longer.
Assertion failure The page produced a different result, or the test assumes the wrong expected value. Read the actual value in the failure output, verify the intended behavior manually, and update either the application or the expectation based on the requirement.
Browser stays open after a failure Cleanup is not protected against exceptions. Keep driver.quit() in a finally block. Use quit to end the whole WebDriver session; close closes only the current window.
Test passes locally but fails intermittently elsewhere Timing, test data, browser differences, or environment assumptions vary. Wait for a meaningful state, isolate test data, avoid relying on machine-specific window dimensions or local state, and capture diagnostic output when a failure occurs.

6. Reliability, speed, and cost as tests grow

For one script, a local browser is usually the simplest way to learn the loop. As the suite grows, use a test runner to report failures and organize repeated setup, then consider remote execution or a browser matrix when your project needs it. Selenium’s getting-started materials link to organizing and executing code and Selenium Grid; add those only after the first test is dependable.

  • Reliability: use isolated, repeatable test data; assert user-visible behavior; wait on conditions; and always close sessions. Avoid tests that depend on another test having run first.
  • Performance: each browser session and page load takes time. Start only the sessions you need, wait for specific states instead of sleeping for a fixed interval, and avoid expanding the browser matrix before it answers a real compatibility question.
  • Cost: local Selenium has no per-screenshot API charge, but browser execution consumes developer or CI compute and maintenance time. Remote grids or hosted browser services may have separate pricing; check the provider’s current terms before adopting one.
  • Diagnostics: print meaningful checkpoints or save a screenshot when a failure occurs. Do not treat a screenshot by itself as proof that an interactive workflow passed; keep the assertion in the test.

7. A screenshot can help diagnose a visual failure

When an assertion fails, a browser screenshot can help show what the test saw. Selenium can save the current browser view to a file:

driver.save_screenshot("failure.png")

Place that call in an exception handler before driver.quit() if you want to preserve evidence on failure. A screenshot captures appearance; it does not replace assertions about the behavior. For page screenshots without writing browser capture plumbing, ScreenshotNeo provides a website screenshot API and MCP server. Its API documentation is at ScreenshotNeo docs.

Or skip the browser setup

If your goal is a page screenshot rather than an interactive pass/fail test, one GET request can capture it. This is not a substitute for the Selenium interaction and assertion shown above; it is a simpler way to obtain a screenshot artifact.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server gives AI agents tools for screenshots and page information. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. See ScreenshotNeo and the API documentation for setup and supported options. Sign up for 1,000 free screenshots a month, no card required.

8. Frequently asked questions

What does a test automation script do?

It performs defined steps against software and checks an expected outcome so that a behavior can be checked repeatedly.

How do I know the script worked?

It should finish with a visible pass message and a successful process exit. A failed assertion or uncaught error should produce a nonzero exit and a useful failure message.

Do I need Selenium if my project already uses Playwright?

No. Use the framework that fits the project and learn its own setup, locator, wait, and assertion patterns from its official documentation.

Can I automate a site that requires login?

Yes, if you are authorized to test it. Use a dedicated test account and controlled test data, and store credentials in environment variables or your CI secret store rather than committing them in the script.

Should the first script use a test runner?

A standalone script keeps the first steps visible. A runner becomes useful when you need repeatable test discovery, structured reports, fixtures, or integration with a larger suite.