Testing Wicket UIs sits in a weird spot. On one side you have WicketTester flying through component checks in milliseconds. On the other side you have Selenium clicking real buttons, waiting for Ajax, and catching the stuff that only shows up when a browser gets involved. If you ship forms, wizards, or grids that dance with Ajax, you need both. The trick is picking what to test where, and keeping it fast and sane.
Right now the browser world moves quick. Chrome ships a new version before your coffee cools, Firefox keeps landing tweaks, and headless drivers like PhantomJS and HTMLUnit are giving CI rooms a quiet way to run end to end flows. Apache Wicket 6 is in solid shape, Java is steady, and teams are asking the same question: how do we test Wicket pages without turning the suite into a flaky monster
Problem framing
Wicket pushes stateful components, models, and wicket:id driven markup. It is great for reuse and behavior, and it hides a lot of request details so you can focus on user flows. The price is that the DOM can be a little, lets say, creative. Generated markup ids change if you shuffle components. Ajax callbacks live inside Wicket JavaScript. A small tweak in a panel can cascade into click targets moving around.
On top of that, Selenium WebDriver runs in the same browsers your users run. That is gold, but it brings timing, waiting, and environment headaches. If you try to click every corner with WebDriver, your build will crawl and break. If you only rely on WicketTester, you will miss real world quirks like CSS overlays blocking clicks or a date picker that needs two taps to settle.
So the frame is simple. Use WicketTester for logic and component behavior. Use WebDriver for the top flows that pay the bills. Keep selectors stable. Bake in Ajax waits that hook into Wicket. Wire the whole thing to your CI so it runs without human babysitting.
Three case walkthrough
Case one: fast feedback with WicketTester
WicketTester is your speed run. It boots a page or component, binds models, fires Ajax events, and lets you assert behaviors without a browser. You can verify that a form binds to the right domain object. You can check that invalid input shows an error message. You can confirm that a link adds a row to a ListView and that a label redraws after Ajax.
Some tips that keep this sharp:
- Test by intent. Look for expected components and messages, not brittle ids. Assert that the submit button is enabled or disabled based on state. Assert that an Ajax behavior is attached to a component when it should.
- Simulate Ajax cleanly. Fire the Ajax event on the component and assert the target updates. You get fast feedback on the model side and the component side without opening a browser.
- Guard the contract. If a panel promises to render a summary label and a delete link, test that contract in WicketTester so refactors do not break your page objects later.
- Keep these tests small. Do not turn WicketTester into an integration sledgehammer. Five to ten assertions per test is plenty.
The payoff is big. Most bugs show up here and you catch them right away. When they pass, you have confidence to only run a handful of browser tests for the real life flows.
Case two: critical paths with Selenium WebDriver
Now the slow lane. You need a browser for checkout, login, account update, and the odd jQuery flavored widget. Use Page Objects to keep those tests readable and keep selectors in one place. Treat them as an API for user actions. LoginPage has fillEmail, fillPassword, and submit. DashboardPage has openSettings and changeAvatar.
Selectors inside page objects are where Wicket can bite. The default generated markup id can change when the component tree moves. You need to bring your own anchors.
- Add data attributes. Put a data attribute in your markup, like data test, with a stable value. WebDriver can find elements by CSS using that attribute, and your UI can evolve without renaming tests.
- Set explicit markup ids where it matters. For a handful of anchors, set a stable id through an attribute modifier. Do this for top flow inputs and buttons, not for every span in the page.
- Prefer semantic hooks. Look for labels, names, placeholders, and visible text that do not change every week. Tests feel more like a user and less like a robot sniffing DOM trivia.
Ajax is the other trap. Clicking a link that triggers Wicket Ajax needs a smart wait. Do not sleep. Tie your waits to Wicket. You can wait until the document reports no active Wicket Ajax requests. That gives you stable timing without guessing seconds. You can also wait for a specific element to appear or change state. Both approaches are better than naps.
Pick drivers by intent. HTMLUnitDriver is fast and quiet, good for smoke checks that hit most pages. PhantomJS is headless but runs real WebKit, so it catches more quirks, and it is still CI friendly. FirefoxDriver gives you the most predictable behavior for rich widgets today. ChromeDriver is quick and keeps getting better. Run one fast headless suite on each commit and keep a small set of real browser flows either on each commit or on a timer.
One more WebDriver note if you use jQuery heavy widgets. Clicks that look obvious to a human can be blocked by fixed headers or animations. Use waits that make sure the element is both visible and clickable. Keep animation durations short in test mode, or toggle them off entirely. You will save a lot of retries.
Case three: cross browser and CI without drama
It is not a test suite until it runs on its own. Wire your stack to Jenkins or TeamCity. Put WicketTester in the unit stage with Maven Surefire. Put WebDriver tests in the integration stage with Maven Failsafe. Keep the fast stuff as a gate on each commit and the slower browser tests on a schedule or on a branch merge.
If your agents are Linux based, wrap the browser run in Xvfb so Firefox and Chrome have a display. For headless runs, PhantomJS drops right in. If you need clean cross browser coverage, Sauce Labs and BrowserStack are doing a solid job with remote sessions. A small Selenium Grid also works if you can keep nodes healthy.
Data setup is where a lot of flakiness starts. Keep tests independent. Use a fast local database like H2 for integration runs or reset your test database between cases. Build data through factories or fixtures, not through brittle UI steps. Log in through the UI once, then reuse the session cookie across steps in the same test when it makes sense. Clean up files and emails. Keep the environment tidy and your suite quiet.
Quick checklist for a calm CI run
- Separate tiers WicketTester fast, WebDriver focused
- Stable selectors data test or explicit ids where it counts
- Ajax aware waits tied to Wicket, not sleeps
- Screenshots on failure and HTML dumps for post mortem
- One headless run per commit small real browser pack on a timer
Objections and replies
We trust Wicket and WicketTester. Do we even need Selenium
WicketTester is perfect for logic. It will not catch CSS overlays, focus traps, date pickers that eat clicks, or broken script bundles. A tiny set of browser checks on top of a big WicketTester base pays for itself the first time a minified script goes bad.
Selenium is flaky by nature
Flakiness usually means waits are naive, selectors are brittle, or test data leaks across tests. Tie waits to Wicket Ajax activity and to element state. Pin selectors to data attributes. Reset state. Keep the UI suite small and meaningful. The flakiness melts away when you remove the guesswork.
Generated ids keep changing and break selectors
Do not chase generated ids. Add your own anchors. data test attributes are cheap and clear. For the few spots where an id makes life easier, set it on purpose. Keep those decisions inside page objects so markup changes do not ripple through tests.
Running browsers on CI is slow
Split the pyramid. Let WicketTester do most of the heavy lifting. Keep five to ten top flows in WebDriver per app. Use headless runs per commit and a nightly pack in real browsers. That gives you safety without dragging the team.
Our app uses a lot of Ajax. Waits become a maze
Make Ajax waits a utility the suite shares. One method waits for Wicket to go idle. Another waits for a specific region to finish updating. Use them everywhere. Stop writing sleeps. Your tests will read better and fail less.
Action oriented close
Here is a short plan you can put in motion this week. It will make your Wicket UI tests faster, calmer, and way more helpful when something breaks.
- Draw your test pyramid Write it down. WicketTester for components and models. WebDriver only for critical user flows and weird widgets. Keep numbers small and focused.
- Pick your selectors Adopt data test across the app. Add it to the handful of inputs and buttons that matter. Teach your page objects to use it. Stop matching on anonymous divs.
- Add Ajax smart waits Centralize waits that watch Wicket Ajax activity and element state. Delete sleeps. Replace them everywhere.
- Create three Page Objects Start with Login, Dashboard, and one key form. Give them clear methods. Move selectors inside. You will feel the difference right away.
- Wire CI stages WicketTester under Surefire, WebDriver under Failsafe. One fast headless run on each commit. A small Firefox and Chrome pack on a timer or at the end of the day.
- Turn on diagnostics Take screenshots and save page source on failure. You will spend less time guessing and more time fixing.
- Stabilize test data Use factories or builders to create users and orders. Reset state between tests. No hidden dependencies.
- Keep a living list of critical flows Review it with your team. Update selectors when the UI evolves. Keep it lean.
This mix wins because it respects what each tool is good at. WicketTester gives you speed and confidence when you change components. Selenium WebDriver keeps you honest in real browsers. Page Objects stop duplication and give new tests a place to live. Ajax smart waits cut most of the flakiness. A clean CI pipeline makes it part of the routine.
Set the bar at the right height. If a test cannot explain what the user is trying to do, it probably belongs in WicketTester, not in a browser. If a bug would only bite a real person with a mouse, it belongs in WebDriver. Keep moving pieces to the right side until your build is fast, stable, and useful.
We are shipping apps into browsers that change every week and networks that lag at the worst time. A balanced approach to testing Wicket UIs with Selenium and beyond keeps you from guessing. You get quick feedback on the server side, and just enough real browser truth to sleep at night. Start small, keep it tidy, and let the suite grow with the app. Your future self will thank you when that late night deploy does not ping your phone.