Debug a Failing Browserless Test
Start with a configured test class from the guide for your application framework. Keep its base class and setup when adding the snapshot annotation. The example below uses a directly constructed view and the plain Java setup.
When a browserless test fails, it can be hard to tell why. The assertion message might say a component wasn’t found or had an unexpected value, but it doesn’t show you what the UI actually looked like. UI snapshots solve this by printing a text representation of the entire component tree at the moment of failure, so you can see exactly what was on screen.
Enabling Snapshots
Snapshots aren’t enabled by default. Add the @ExtendWith(TreeOnFailureExtension.class) annotation to your test class:
Source code
Java
@ExtendWith(TreeOnFailureExtension.class)
class HelloWorldViewTest extends BrowserlessTest {
...
}For Java EE/CDI, add the same annotation to the existing CDI-aware test class:
Source code
Java
@ExtendWith(TreeOnFailureExtension.class)
class CdiGreetingViewTest extends AbstractCdiViewTest {
// Keep the test methods from the CDI guide.
}When any test in the class fails, the extension automatically prints the UI tree to the test output alongside the failure message.
See Snapshot Format for the properties represented in the output.
Using Snapshots to Debug Failures
Suppose you have a view like this:
Source code
Java
@Route("")
public class HelloWorldView extends HorizontalLayout {
TextField name;
Button sayHello;
public HelloWorldView() {
name = new TextField("Your name");
sayHello = new Button("Say hello");
sayHello.addClickListener(e -> {
if (!name.getValue().isEmpty()) {
Notification.show("Hello " + name.getValue());
}
});
add(name, sayHello);
}
}And a test for it:
Source code
Java
@Test
public void clickSayHello_showsGreeting() {
HelloWorldView view = navigate(HelloWorldView.class);
test(view.sayHello).click();
Notification notification = find(Notification.class).single();
assertEquals("Hello World", test(notification).getText());
}The test fails because no Notification was found. The assertion error alone doesn’t explain why. With snapshots enabled, the test output includes the UI tree:
Source code
└── UI[]
└── HelloWorldView[@theme='margin spacing']
├── TextField[label='Your name', value='']
└── Button[caption='Say hello']Now you can see:
-
There’s no
Notificationin the tree — the click didn’t produce one. -
The
TextFieldhasvalue=''— the name field is empty. -
Looking back at the view code, the click handler only opens the notification when the name is nonempty. The test forgot to set the name before clicking.
Set the name before clicking the button, then rerun the test:
Source code
Java
test(view.name).setValue("World");
test(view.sayHello).click();
Notification notification = find(Notification.class).single();
Assertions.assertEquals("Hello World", test(notification).getText());Tips
-
Look for what’s missing. If a query like
find(Notification.class).single()fails, the snapshot shows you that the component isn’t there. Check the tree for clues about why it wasn’t created. -
Check property values. When an assertion on a component’s text or value fails, find that component in the tree and compare its actual properties to what you expected.
-
Watch for unexpected components. If
find(Button.class).single()fails because multiple buttons were found, the snapshot shows you all of them so you can narrow your query. -
Inspect the layout hierarchy. If a component appears in the tree but a scoped query like
findInView(TextField.class)can’t find it, the snapshot helps you see whether the component is nested inside the expected parent.
7B14417A-0C9B-4B46-8945-AC2564AD5F82