How to test a web app with Selenium

To test a web app with Selenium, you write short programs that open a real browser, carry out the steps a user would and check that the page shows the right result. Selenium supplies the part that controls the browser. A test framework, such as NUnit for .NET or JUnit for Java, runs the tests and reports which passed. This article covers what Selenium consists of in 2026, a first test, the habits that keep a suite dependable and when a different tool would suit you better.

What Selenium consists of

Selenium is a free, open-source project. Selenium 4 is the current major version, and the project publishes a point release every few weeks. Its parts are:

  • WebDriver. The core of the project: a programming interface for driving a browser, with official libraries for Java, Python, C#, Ruby and JavaScript. It implements the W3C WebDriver specification, a web standard, so one test can run against Chrome, Edge, Firefox and Safari.
  • Selenium Manager. Each browser needs a matching driver program, and keeping the two in step used to be a regular chore. Selenium Manager, included since version 4.6, finds and downloads the right driver automatically. The project still labels it beta.
  • Selenium Grid. Runs tests on several machines and browsers at once, which shortens a long test run.
  • Selenium IDE. A browser extension for Chrome, Firefox and Edge that records your actions and plays them back. It is handy for a first sketch of a test. In our view recorded scripts are too brittle to be the basis of a suite you intend to keep.

Two further points are worth knowing. WebDriver BiDi is a newer W3C standard that lets the test and the browser talk in both directions, so a test can listen for network requests, console messages and JavaScript errors as they happen. Selenium’s documentation says the project is moving its implementation from the original WebDriver protocol to BiDi while keeping backwards compatibility as far as it can.

The other concerns old applications. Selenium stopped supporting standalone Internet Explorer in June 2022, but its Internet Explorer driver can still drive Microsoft Edge in IE mode. That matters if you have an older intranet application that only works that way.

A first test

This example is in C# with NUnit. It signs in to a test copy of an application and checks that the welcome message appears.

using System;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;

public class SignInTests
{
    [Test]
    public void Valid_user_sees_the_welcome_message()
    {
        using var driver = new ChromeDriver();
        driver.Navigate().GoToUrl("https://test.example.co.uk/sign-in");

        driver.FindElement(By.Id("email")).SendKeys("test.user@example.co.uk");
        driver.FindElement(By.Id("password")).SendKeys("a-test-password");
        driver.FindElement(By.CssSelector("button[type='submit']")).Click();

        var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
        var welcome = wait.Until(d => d.FindElement(By.Id("welcome-message")));

        Assert.That(welcome.Text, Does.Contain("Test User"));
    }
}

Read from the top, the test starts Chrome, opens the sign-in page, types an email address and password and clicks the button. It then waits up to ten seconds for the welcome message to appear, and checks its text. The browser closes when the test ends. Every Selenium test has this shape: go somewhere, find elements, act on them, wait for the result, check it.

Habits that keep a suite reliable

Browser tests have a reputation for failing at random. Most of that comes from a small number of avoidable mistakes.

Wait for a condition, never for a fixed time. The test and the browser run at different speeds. Selenium’s documentation describes the resulting race as one of the primary causes of flaky tests. The remedy is the explicit wait shown above, which polls until the element is there. The same documentation warns against mixing explicit waits with the global implicit wait setting, because the combination gives unpredictable timings.

Use locators that survive a redesign. A test finds a button by some property of it. An ID or a dedicated test attribute is stable. A position, such as “the third button in the second panel”, breaks when the layout changes. Ask the developers to add identifiers where they are missing.

Keep each screen’s details in one place. The page object pattern puts everything the tests know about a screen into one class. When the screen changes, one file changes, and the tests that use it do not.

Make tests independent. Each test should create the data it needs and start with a fresh browser. Tests that rely on what an earlier test left behind fail in ways that are hard to trace.

Run them against a test environment with known data. Never against the live system.

Run them automatically. A suite that runs on every change, or every night, stays healthy because failures are noticed at once. A suite run by hand now and then decays.

Keep the suite small. Browser tests are the slowest and most fragile kind. Cover the main workflows with them and leave detailed checking of rules to faster tests lower down, as described in our overview of software testing strategies.

Using Selenium on a system with no tests

Browser tests have a particular use on older systems. When we take over an application someone else built, there are often no automated tests, and the code may not be arranged so that small tests can be added without altering it. A browser test needs no change to the code. It treats the application as a sealed unit, which is the black box approach.

The method is to record the important workflows as they behave today, running against a restored copy of the system. These are characterisation tests: they capture what the system does, not what anyone thinks it should do. For each workflow, a named person in the business confirms the recorded behaviour is correct. From then on the tests serve as a regression suite, run after every change.

One practical warning for older Microsoft applications: ASP.NET Web Forms pages generate long element IDs automatically, and these can shift when a page is rearranged. Agree how elements will be identified before writing many tests.

Selenium, Playwright or Cypress

Selenium is no longer the only serious choice. Playwright and Cypress are both widely used, and each documents its own strengths.

SeleniumPlaywrightCypress
Who is behind itThe Selenium open-source projectMicrosoft, as open sourceCypress, with a free open-source app and a paid cloud service
Test languagesJava, Python, C#, Ruby, JavaScriptJavaScript or TypeScript on Node.js, Python, Java, .NETJavaScript or TypeScript
BrowsersChrome, Edge, Firefox, Safari, and Edge in IE modeChromium, Firefox and WebKit, the engine behind SafariChrome-family browsers including Edge, and Firefox
WaitingExplicit waits written into the testWaits automatically for elements to be readyCommands and checks retry automatically for a short time

For a new suite, many teams now start with Playwright, largely because its automatic waiting removes the commonest cause of unreliable tests. Selenium remains a sound choice where a suite already exists, where the team writes Ruby, or where you need Safari itself or Edge in IE mode. A working Selenium suite is not worth rewriting for fashion.

Before you commission browser tests

  • List the five workflows that would hurt most if they broke. Start with those.
  • For each, name the person who can say whether the result is correct.
  • Confirm there is a test environment whose data can be reset.
  • Decide where the tests will run and who sees a failure.
  • Budget for upkeep. Tests need changing when screens change, and a suite nobody maintains is soon ignored.

The first two items need no technical skill and can be done this week. They are also the part a supplier cannot do for you.

Tell us about your system

Say what it does, what it is built on and what is worrying you. We will reply with what we would look at first and whether we are the right people to help.

Tell us about your system 0800 433 7990 Monday to Friday, 9am to 5pm. A first 20-minute call is free, and we reply to every enquiry within one working day. What happens after you get in touch