Skip to main content
Every feature or bug fix merged into LibWeb should be accompanied by a test. Ladybird’s test suite lives in the Tests/ directory, with Tests/LibWeb/ dedicated to browser-engine tests. The suite supports four test types — Text, Layout, Ref, and Screenshot — and integrates with the Web Platform Tests (WPT) project for broad standards coverage. This page explains how to run the existing tests, how to write new ones, and how to reproduce CI failures locally.

Running Tests

The Meta/ladybird.py script is the easiest way to run tests:

Using ctest Directly

You can also drive the build and tests entirely through CMake presets:
Some tests require the LADYBIRD_SOURCE_DIR environment variable to point to the root of the Ladybird source tree:
After a build you can also run tests via Ninja:
To see stdout/stderr output from failing tests, set CTEST_OUTPUT_ON_FAILURE:

Running with Sanitizers

CI runs all host tests with Address Sanitizer (ASAN) and Undefined Behaviour Sanitizer (UBSAN) enabled. To reproduce a CI failure locally, use the Sanitizer preset and set the same environment variables that CI uses.
ASAN detects memory leaks, out-of-bounds accesses, and use-after-free bugs. UBSAN catches signed integer overflow and other undefined behaviour. Sanitizer builds take significantly longer and interact poorly with caches such as ccache.
To match CI behaviour exactly from a Lagom build, set the sanitizer options manually:

Web Platform Tests (WPT)

The WPT integration is driven by the Meta/WPT.sh script.

Importing WPT Tests

When your code changes cause Ladybird to pass WPT tests it previously failed, you can import those tests directly into the repository:
Pass the path component of any http://wpt.live/ URL. The script downloads the test and its JavaScript dependencies, copies them to Tests/LibWeb/<test-type>/input/wpt-import/, runs the test, and writes the expected output to Tests/LibWeb/<test-type>/expected/wpt-import/.

Writing Tests

Creating Test Files

Use the helper script to generate a new test with correct boilerplate:
The accepted values for test_type are Text, Layout, Ref, and Screenshot. The script creates:
  • An input HTML file at Tests/LibWeb/<test_type>/input/your-new-test-name.html
  • A corresponding expectations file in Tests/LibWeb/<test_type>/expected/
After replacing the boilerplate with your actual test, regenerate the expectations file (see Rebaselining below).

Test Types

Text tests exercise Web APIs that have no visual representation. They run in a headless browser and are written in JavaScript. Each test calls println() to emit output lines, which are accumulated and compared against a saved expected-output file.Tests can be synchronous or asynchronous. Async tests use a done callback to signal completion; the test function itself can be async if an async context is needed.

Rebaselining

After updating a Text or Layout test, regenerate its expectations file:
1

Create the test file

Run ./Tests/LibWeb/add_libweb_test.py your-test-name test_type to generate the boilerplate input and expectations files.
2

Write the test

Replace the generated boilerplate in Tests/LibWeb/<test_type>/input/your-test-name.html with your actual test logic.
3

Regenerate expectations

For Text and Layout tests, rebaseline: ./Meta/ladybird.py run test-web --rebaseline -f <type>/input/your-test-name.html.For Ref tests, write the equivalent-rendering HTML reference page manually.For Screenshot tests, generate the reference PNG using headless mode (see above).
4

Run the tests

Verify your new test passes: Meta/ladybird.py test LibWeb.
5

Check with sanitizers (optional)

To confirm the test is clean under ASAN/UBSAN, build with the Sanitizer preset and run ctest --preset Sanitizer.