Files
ladybird/Tests/LibWeb/test-web/Application.cpp
Timothy Flynn 6d52c9003c test-web: Add an explicit verbosity mode to disable live display
We were previously using the absence of a results directory to decide
if we should disable live display. However, this was never the case -
the results directory would become unconditionally set in main(). This
caused all test-web output in CI to become hidden.

Instead, let's add a verbosity mode to display test output explicitly.
This is set for CI.

This also makes it much easier to debug single tests locally. The live
capture and results file combo is a bit overkill for running a single
test; we can now just add "-v" to the command line to see the output
directly in the terminal.
2026-01-20 14:14:38 -05:00

108 lines
4.3 KiB
C++

/*
* Copyright (c) 2024-2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "Application.h"
#include "Fixture.h"
#include <LibCore/ArgsParser.h>
#include <LibCore/Environment.h>
#include <LibCore/System.h>
namespace TestWeb {
Application::Application(Optional<ByteString> ladybird_binary_path)
: WebView::Application(move(ladybird_binary_path))
, test_concurrency(Core::System::hardware_concurrency())
, python_executable_path("python3")
{
if (auto ladybird_source_dir = Core::Environment::get("LADYBIRD_SOURCE_DIR"sv); ladybird_source_dir.has_value())
test_root_path = LexicalPath::join(*ladybird_source_dir, "Tests"sv, "LibWeb"sv).string();
}
Application::~Application()
{
for (auto& fixture : Fixture::all())
fixture->teardown();
}
void Application::create_platform_arguments(Core::ArgsParser& args_parser)
{
args_parser.add_option(test_root_path, "Path containing the tests to run", "test-path", 0, "path");
args_parser.add_option(results_directory, "Directory to store test results", "results-dir", 'R', "path");
args_parser.add_option(test_concurrency, "Maximum number of tests to run at once", "test-concurrency", 'j', "jobs");
args_parser.add_option(test_globs, "Only run tests matching the given glob", "filter", 'f', "glob");
args_parser.add_option(python_executable_path, "Path to python3", "python-executable", 'P', "path");
args_parser.add_option(dump_failed_ref_tests, "Dump screenshots of failing ref tests", "dump-failed-ref-tests", 'D');
args_parser.add_option(dump_gc_graph, "Dump GC graph", "dump-gc-graph", 'G');
args_parser.add_option(test_dry_run, "List the tests that would be run, without running them", "dry-run");
args_parser.add_option(rebaseline, "Rebaseline any executed layout or text tests", "rebaseline");
args_parser.add_option(shuffle, "Shuffle the order of tests before running them", "shuffle", 's');
args_parser.add_option(per_test_timeout_in_seconds, "Per-test timeout (default: 30)", "per-test-timeout", 't', "seconds");
args_parser.add_option(Core::ArgsParser::Option {
.argument_mode = Core::ArgsParser::OptionArgumentMode::Optional,
.help_string = "Log extra information about test results (use multiple times for more information)",
.long_name = "verbose",
.short_name = 'v',
.accept_value = [&](StringView value) -> ErrorOr<bool> {
if (value.is_empty() && verbosity < NumericLimits<u8>::max()) {
++verbosity;
return true;
}
return false;
},
});
}
void Application::create_platform_options(WebView::BrowserOptions& browser_options, WebView::RequestServerOptions& request_server_options, WebView::WebContentOptions& web_content_options)
{
browser_options.headless_mode = WebView::HeadlessMode::Test;
browser_options.disable_sql_database = WebView::DisableSQLDatabase::Yes;
request_server_options.http_disk_cache_mode = WebView::HTTPDiskCacheMode::Testing;
web_content_options.is_test_mode = WebView::IsTestMode::Yes;
// Allow window.open() to succeed for tests.
browser_options.allow_popups = WebView::AllowPopups::Yes;
// Ensure consistent font rendering between operating systems.
web_content_options.force_fontconfig = WebView::ForceFontconfig::Yes;
// Ensure tests are resilient to minor changes to the viewport scrollbar.
web_content_options.paint_viewport_scrollbars = WebView::PaintViewportScrollbars::No;
// Ensure consistent time zone operations across different machine configurations.
web_content_options.default_time_zone = "UTC"sv;
if (dump_gc_graph) {
// Force all tests to run in serial if we are interested in the GC graph.
test_concurrency = 1;
}
}
ErrorOr<void> Application::launch_test_fixtures()
{
Fixture::initialize_fixtures();
// FIXME: Add option to only run specific fixtures from command line by name
// And an option to not run any fixtures at all
for (auto const& fixture : Fixture::all()) {
if (auto result = fixture->setup(web_content_options()); result.is_error())
return result;
}
return {};
}
bool Application::should_capture_web_content_output() const
{
return verbosity < Application::VERBOSITY_LEVEL_LOG_TEST_OUTPUT;
}
}