Speed Up Browserless Tests
- Restrict Package Scanning
- Use a Reduced Spring Application Context
- Share the Vaadin Environment in Plain Java
- Compare Execution Time
This guide covers default route scanning, Spring application contexts, and plain Java environment sharing. For Java EE/CDI, keep the Weld setup in the CDI guide; tune its explicit bean archive and route registrations instead of applying Spring configuration or replacing it with a plain JUnit extension.
By default, browserless tests scan the entire classpath for routes and error views and, in Spring Boot projects, load the full application context. For large projects this can slow down test startup. The following techniques help reduce bootstrap time.
Restrict Package Scanning
This applies to the default route-discovery setup. The CDI guide overrides that setup and registers routes explicitly. The example below is for Spring Boot.
Use a class from each view package to keep the scan focused and safe to refactor:
Source code
Java
@SpringBootTest
@ViewPackages(classes = MyView.class)
class MyViewTest extends SpringBrowserlessTest {
}See Route Scanning for all annotation forms.
Use a Reduced Spring Application Context
Instead of @SpringBootTest, which loads the full application context, you can annotate the test with @ContextConfiguration to provide only the beans needed for the test. This is useful when you want to replace real services with test doubles.
For a view that injects a service, register a test implementation with the same interface. This example uses a service-backed variant of the greeting view:
Source code
Java
public interface GreetingService {
String greet(String name);
}
@Route("service-greeting")
public class ServiceGreetingView extends HorizontalLayout {
final TextField name = new TextField("Your name");
final Button sayHello = new Button("Say hello");
public ServiceGreetingView(GreetingService greetings) {
sayHello.addClickListener(event ->
Notification.show(greetings.greet(name.getValue())));
add(name, sayHello);
}
}Place each public type in its own file. Put the test in the view’s package:
Source code
Java
@ViewPackages(classes = ServiceGreetingView.class)
@ContextConfiguration(classes = ViewTestConfig.class)
class ViewTest extends SpringBrowserlessTest {
@Test
void greeting_usesTestService() {
var view = navigate(ServiceGreetingView.class);
test(view.name).setValue("Test");
test(view.sayHello).click();
Notification notification = find(Notification.class).single();
Assertions.assertEquals("Hello Test", test(notification).getText());
}
}
@Configuration
class ViewTestConfig {
@Bean
GreetingService greetingService() {
return name -> "Hello " + name;
}
}|
Note
|
Prefer replacing services this way — a test Bean overrides create separate cached Spring contexts and can affect authentication in browserless test suites. See Application Context Isolation for the integration behavior. For service-level tests that don’t need the Vaadin context, an even simpler option is to construct the service directly with stub collaborators (for example |
Share the Vaadin Environment in Plain Java
By default, the Vaadin environment — the session, the UI, and all routes — is created before every test method and torn down after. For classes with many tests that navigate to views sharing the same MainLayout, this setup cost can dominate the test runtime.
To reuse a single Vaadin environment across all test methods in a class, register a static BrowserlessClassExtension with @RegisterExtension. The extension initializes the environment once before all tests and tears it down after all tests, sharing the same UI instance across every method. Use the extension instance for navigation and queries.
This option applies to plain Java tests; keep the framework-specific base class for Spring and Quarkus tests.
Source code
Shared Environment Example
@ViewPackages(classes = HelloWorldView.class)
class HelloWorldViewTest {
@RegisterExtension
static BrowserlessClassExtension extension = new BrowserlessClassExtension();
@BeforeAll
static void setup() {
extension.navigate(HelloWorldView.class);
}
@Test
void name_isInitiallyEmpty() {
Assertions.assertEquals("", extension.find(TextField.class)
.withLabel("Your name").single().getValue());
}
@Test
void greetingButton_isEnabled() {
Assertions.assertTrue(extension.find(Button.class)
.withText("Say hello").single().isEnabled());
}
}These read-only tests use the HelloWorldView from the plain Java setup guide.
They can run in either order because neither changes the shared UI.
|
Warning
| With a shared environment, state leaks between tests. Tests that mutate state must reset it explicitly. Re-navigating can reset view-local state, but does not reset session or application-owned data. Prefer a shared environment for read-only or independent interactions; stick with the default per-method lifecycle when tests mutate shared state in conflicting ways. |
|
Note
|
The base test classes — BrowserlessTest, SpringBrowserlessTest, and QuarkusBrowserlessTest — always reinitialize the Vaadin environment before each test method. Annotating them with @TestInstance(PER_CLASS) therefore does not share the Vaadin environment, although it can still be useful for sharing other per-class state. Use a static BrowserlessClassExtension as shown above to share the Vaadin environment.
|
Compare Execution Time
Run the same suite before and after each change. Keep the default per-method environment unless sharing it provides a useful improvement and the tests reset their state reliably. JUnit extensions are for plain Java tests; they do not replace the Spring or Quarkus base classes. See JUnit 6 Extensions for lifecycle contracts.
A3B7E2F1-5D89-4C6A-9E12-7F4A8B3C6D50